java 线程交互之wait/notify

众所周知java支持多线程,有多线程就必然会存在多线程的交互,交互方式有多种,比如通过共享数据,或者通过提供的锁信号量等等,这里通过用wait以及notify实现线程交互。

 

要用好线程的wait和notify就要首先了解一下线程的状态,线程的状态大致可以划分为一下几种,创建->就绪->运行->阻塞->销毁

一个线程通过new 到调用start完成了创建到就绪,这个之后就是等待cpu分配资源运行,阻塞的状态是发生在线程运行状态之后,发生线程阻塞的情况有很多种,这里简单的列举一下

                             1>锁阻塞

                             2>调用wait阻塞

                             3>调用join阻塞

                             4>调用sleep阻塞

 

当然线程也可以从运行状态返回到就绪状态,这个是通过调用Thread类的yeild方法实现的,这里简单说明一下,wait以及notify和notifyall是在超父类Object中提供的,也就是说属于类的

,而sleep/join/yeild是Thread这个类提供的,也即是属于线程的

从上可知,wait以及notify是只能用在对象锁上,不能和共享锁一起使用即只能和synchroized这个关键之一起使用,也就是说用wait和notify之前,必须先获得对象的锁,当调用wait的时候,

线程被放入对象监视器的等待队列里面,而且会释放锁,等待其他线程调用notify从锁对象监视器的等待队列里,取得一个线程执行,记着,synchronized是对象锁,就是说她要锁整个对象。

 

通过以上我们大致了解了,wait和notify的知识点,下面请看例子,简单的生产者消费者的例子

 1 public class Test {
 2 
 3     private static List<Integer> queue = new ArrayList<>();
 4     
 5     
 6     /**
 7      * 生产者
 8      * @param n     void
 9      *     
10      */ 
11     public synchronized void producer(int n){
12         System.out.println("insert data "+n);
13         queue.add(n);
14         
15         if(queue.size()==1)
16             this.notify();
17     }
18     
19     /**
20      * 消费者
21      * @return     int
22      *     
23      */ 
24     public synchronized int consumer(){
25             try {
26                 if(queue.isEmpty())
27                     this.wait();
28             } catch (InterruptedException e) {
29                 e.printStackTrace();
30             }
31         int result = queue.get(0);
32         queue.remove(0);
33         return result;
34     }
35     
36     public static void main(String[] args) {
37         final Test test = new Test();
38         
39         Thread thread1 = new Thread(new Runnable() {//生产线程
40             
41             @Override
42             public void run() {
43                 Random random = new Random();
44                 try {
45                     while(true){
46                         test.producer(random.nextInt(1000));
47                         Thread.sleep(2000);
48                     }
49                 } catch (InterruptedException e) {
50                     e.printStackTrace();
51                 }
52             }
53         });
54         
55         Thread thread2 = new Thread(new Runnable() {//消费线程
56             
57             @Override
58             public void run() {
59                 try {
60                     while(true){
61                         System.out.println("select data is "+test.consumer());
62                         Thread.sleep(1000);
63                     }
64                 } catch (InterruptedException e) {
65                     e.printStackTrace();
66                 }
67             }
68         });
69         
70         thread1.start();
71         thread2.start();
72     }
73 }

 

以上是个人的理解,如有误的地方,欢迎大家批评指正,不胜感激

posted on 2014-10-10 14:40  墙头上一根草  阅读(551)  评论(0编辑  收藏  举报