Java多线程之线程间协作 notify与wait的使用

(转载请注明出处:http://blog.csdn.net/buptgshengod

1.背景

       Java多线程操作运用很广,特别是在android程序方面。线程异步协作是多线程操作的难点也是关键,也是找工作面试经常考到的地方。下面分享一下我的使用心得。

介绍几个关键字:

synchronized:线程锁,使得系统只执行当前线程。

notifyAll():唤醒其它被锁住的线程

wait():挂起线程

ExecutorService exec=Executors.newCachedThreadPool();:创建线程池

exec.execute( new Runnable() ):将线程放到线程池中管理

2.代码部分

(1)

public class Thread2 {
     public void m4t1() {
          synchronized(this) {
               int i = 5;
               while(i>0) {
                    System.out.println("1");
                    i--;

                    try {
                         Thread.sleep(500);

                    } catch (InterruptedException ie) {
                    }
               }
          }
     }
     public void m4t2() {
        // synchronized(this){
         int i = 5;
          while( i > 0) {
               System.out.println("2");
               i--;
               try {
                    Thread.sleep(500);

               } catch (InterruptedException ie) {
               }
          }

     }
     public static void main(String[] args) {
          final Thread2 myt2 = new Thread2();
          Thread t1 = new Thread(  new Runnable() {  public void run() {  myt2.m4t1();  }  }, "t1"  );
          Thread t2 = new Thread(  new Runnable() {  public void run() { myt2.m4t2();   }  }, "t2"  );
          t1.start();
          t2.start();

     }
}

我们发现,两个线程其中一个上了锁,另一个没有上锁。运行结果如下。说明了虽然一个线程上了锁,但是还是能被让其它未上锁线程访问。

(2)

当我们给两个方法都加上锁

public class Thread2 {
     public void m4t1() {
          synchronized(this) {
               int i = 5;
               while(i>0) {
                    System.out.println("1");
                    i--;

                    try {
                         Thread.sleep(500);

                    } catch (InterruptedException ie) {
                    }
               }
          }
     }
     public void m4t2() {
        synchronized(this){
         int i = 5;
          while( i > 0) {
               System.out.println("2");
               i--;
               try {
                    Thread.sleep(500);

               } catch (InterruptedException ie) {
               }
          }
        }

     }
     public static void main(String[] args) {
          final Thread2 myt2 = new Thread2();
          Thread t1 = new Thread(  new Runnable() {  public void run() {  myt2.m4t1();  }  }, "t1"  );
          Thread t2 = new Thread(  new Runnable() {  public void run() { myt2.m4t2();   }  }, "t2"  );
          t1.start();
          t2.start();

     }
}

运行结果变成了

先执行完第一个锁中的内容后执行第二个锁中的内容。

(3)

这时候我们使用notifyAll()和wait()

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Thread2 {
     public void m4t1() {
          synchronized(this) {
               int i = 5;
               while(i>0) {
                    System.out.println("1");
                    i--;

                    try {
                         Thread.sleep(500);
                         notifyAll();
                         wait();
                    } catch (InterruptedException ie) {
                    }
               }
          }
     }
     public void m4t2() {
        synchronized(this){
         int i = 5;
          while( i > 0) {
               System.out.println("2");
               i--;
               try {
                    Thread.sleep(500);
                    notifyAll();
                    wait();
               } catch (InterruptedException ie) {
               }
          }
        }

     }
     public static void main(String[] args) {
          final Thread2 myt2 = new Thread2();
          Thread t1 = new Thread(  new Runnable() {  public void run() {  myt2.m4t1();  }  }, "t1"  );
          Thread t2 = new Thread(  new Runnable() {  public void run() { myt2.m4t2();   }  }, "t2"  );
          t1.start();
          t2.start();

     }
}


通过不断的唤醒再挂起,两个线程又交替运行。


(4)

如果想让代码更完善,可以将两个线程放到线程池

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Thread2 {
     public void m4t1() {
          synchronized(this) {
               int i = 5;
               while(i>0) {
                    System.out.println("1");
                    i--;

                    try {
                         Thread.sleep(500);
                         notifyAll();
                         wait();
                    } catch (InterruptedException ie) {
                    }
               }
          }
     }
     public void m4t2() {
        synchronized(this){
         int i = 5;
          while( i > 0) {
               System.out.println("2");
               i--;
               try {
                    Thread.sleep(500);
                    notifyAll();
                    wait();
               } catch (InterruptedException ie) {
               }
          }
        }

     }
     public static void main(String[] args) {
          final Thread2 myt2 = new Thread2();
         ExecutorService exec=Executors.newCachedThreadPool();
         exec.execute( new Runnable() {  public void run() {  myt2.m4t1();  }  });
         exec.execute( new Runnable() {  public void run() {  myt2.m4t2();  }  });
     }
}
时间: 2024-08-30 03:38:53

Java多线程之线程间协作 notify与wait的使用的相关文章

JAVA线程间协作:wait.notify.notifyAll

    JAVA的进程同步是通过synchronized()来实现的,需要说明的是,JAVA的synchronized()方法类似于操作系统概念中的互斥内存块,在JAVA中的Object类型中,都是带有一个内存锁的,在有线程获取该内存锁后,其它线程无法访问该内存,从而实现JAVA中简单的同步.互斥操作.明白这个原理,就能理解为什么synchronized(this)与synchronized(static XXX)的区别了,synchronized就是针对内存区块申请内存锁,this关键字代表类

线程间协作的两种方式:wait、notify、notifyAll和Condition

在前面我们将了很多关于同步的问题,然而在现实中,需要线程之间的协作.比如说最经典的生产者-消费者模型:当队列满时,生产者需要等待队列有空间才能继续往里面放入商品,而在等待的期间内,生产者必须释放对临界资源(即队列)的占用权.因为生产者如果不释放对临界资源的占用权,那么消费者就无法消费队列中的商品,就不会让队列有空间,那么生产者就会一直无限等待下去.因此,一般情况下,当队列满时,会让生产者交出对临界资源的占用权,并进入挂起状态.然后等待消费者消费了商品,然后消费者通知生产者队列有空间了.同样地,当

java-并发-线程间协作的两种方式:wait、notify、notifyAll和Condition

线程之间的协作.比如说最经典的生产者-消费者模型:当队列满时,生产者需要等待队列有空间才能继续往里面放入商品,而在等待的期间内,生产者必须释放对临界资源(即队列)的占用权.因为生产者如果不释放对临界资源的占用权,那么消费者就无法消费队列中的商品,就不会让队列有空间,那么生产者就会一直无限等待下去.因此,一般情况下,当队列满时,会让生产者交出对临界资源的占用权,并进入挂起状态.然后等待消费者消费了商品,然后消费者通知生产者队列有空间了.同样地,当队列空时,消费者也必须等待,等待生产者通知它队列中有

学习Java多线程之线程定义、状态和属性_java

一 .线程和进程 1. 什么是线程和进程的区别: 线程是指程序在执行过程中,能够执行程序代码的一个执行单元.在java语言中,线程有四种状态:运行 .就绪.挂起和结束. 进程是指一段正在执行的程序.而线程有事也被成为轻量级的进程,他得程序执行的最小单元,一个进程可以拥有多个线程,各个线程之间共享程序的内功空间(代码段.数据段和堆空间)及一些进程级的资源(例如打开的文件),但是各个线程都拥有自己的棧空间. 2. 为何要使用多进程 在操作系统级别上来看主要有以下几个方面: - 使用多线程可以减少程序

Java并发——线程间协作(wait、notify、sleep、yield、join)

1 线程的状态 Java中线程中状态可分为五种:New(新建状态),Runnable(就绪状态),Running(运行状态),Blocked(阻塞状态),Dead(死亡状态). New:新建状态,当线程创建完成时为新建状态,即new Thread(...),还没有调用start方法时,线程处于新建状态 Runnable:就绪状态,当调用线程的的start方法后,线程进入就绪状态,等待CPU资源.处于就绪状态的线程由Java运行时系统的线程调度程序(*thread scheduler*)来调度 R

Java多线程中的wait与notify,notifyall例子

在Java多线程编程中,wait()的作用的是让当前线程进入阻塞状态,notify()是让当前线程唤醒继续执行.虽然是对线程状态的控制,但它们其实都是Object中的方法,这是因为wait与notify所起的作用与线程间的互斥锁有关. 在执行wait()和notify()之前,必须要先获得互斥锁,即一定要和synchronized一起使用.wait()的含义是让出获得的互斥锁,并让自己进入阻塞状态.在notify()的时候也已经获得了互斥锁,所做的事情就是唤醒当前线程继续执行. 假如synchr

java 多线程和线程池

● 多线程 多线程的概念很好理解就是多条线程同时存在,但要用好多线程确不容易,涉及到多线程间通信,多线程共用一个资源等诸多问题. 使用多线程的优缺点: 优点: 1)适当的提高程序的执行效率(多个线程同时执行). 2)适当的提高了资源利用率(CPU.内存等). 缺点: 1)占用一定的内存空间. 2)线程越多CPU的调度开销越大. 3)程序的复杂度会上升. 对于多线程的示例代码感兴趣的可以自己写Demo啦,去运行体会,下面我主要列出一些多线程的技术点. synchronized 同步块大家都比较熟悉

java多线程之线程安全的单例模式_java

概念: java中单例模式是一种常见的设计模式,单例模式分三种:懒汉式单例.饿汉式单例.登记式单例三种. 单例模式有一下特点: 1.单例类只能有一个实例. 2.单例类必须自己创建自己的唯一实例. 3.单例类必须给所有其他对象提供这一实例. 单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例.在计算机系统中,线程池.缓存.日志对象.对话框.打印机.显卡的驱动程序对象常被设计成单例.这些应用都或多或少具有资源管理器的功能.每台计算机可以有若干个打印机,但只能有一个Printer

Java多线程和线程池

版权声明:本文为博主原创文章,转载注明出处http://blog.csdn.net/u013142781 1.为什么要使用线程池 在Java中,如果每个请求到达就创建一个新线程,开销是相当大的.在实际使用中,服务器在创建和销毁线程上花费的时间和消耗的系统资源都相当大,甚至可能要比在处理实际的用户请求的时间和资源要多的多.除了创建和销毁线程的开销之外,活动的线程也需要消耗系统资源.如果在一个jvm里创建太多的线程,可能会使系统由于过度消耗内存或"切换过度"而导致系统资源不足.为了防止资源