1 wait notify

wait/notify:

    wait()使线程停止,notify使wait状态的线程继续执行。

    wait()是Object类的方法,该方法用来将线程置入“预执行队列”,并在wait()方法处停止执行,直到接到通知或被中断为止。调用wait()方法必须要获得对象的锁,即只能在同步方法或同步块中调用wait()方法。调用wait()方法后,对象的锁被当前线程释放。

   notify()也是在同步块或同步方法中调用,调用前必须获得对象的锁,该方法用来通知那些等待该对象的锁的其它线程。如果有多个线程等待,则挑选一个wait()状态线程,对其发出通知,如果没有线程等待,则该命令被忽略。在该notify()方法所在的synchronized块或方法执行完毕后,才使被挑选的线程获取该对象的锁。

注意:如果调用wait() 或notify() 没有持有对象的锁,会抛出IlegalMonitorStateException异常。

 1 package multiMethod.waitNotify;
 2 
 3 import java.util.LinkedList;
 4 import java.util.List;
 5 import java.util.concurrent.atomic.AtomicInteger;
 6 
 7 public class MyList {
 8     private List<String> list = new LinkedList<String>();
 9     private AtomicInteger count = new AtomicInteger(0);
10     private int maxSize, minSize;
11     private Object lock = new Object();
12 
13     public MyList(int maxSize, int minSize) {
14         this.maxSize = maxSize;
15         this.minSize = minSize;
16     }
17 
18     public void add() {
19         synchronized (lock) {
20             try {
21                 if (getSize() == maxSize) {
22                     lock.wait();
23                 }
24             } catch (Exception e) {
25             }
26             list.add("hello");
27             System.out.println("add ...");
28             count.incrementAndGet();
29             lock.notify();
30         }
31     }
32 
33     public void take() {
34         synchronized (lock) {
35             try {
36                 if (getSize() <= minSize) {
37                     lock.wait();
38                 }
39             } catch (Exception e) {
40                 // TODO: handle exception
41             }
42             list.remove(count.get()-1);
43             System.out.println("take().......");
44             this.count.decrementAndGet();
45             lock.notify();
46         }
47     }
48 
49     public int getSize() {
50         return count.get();
51     }
52 
53     public static void main(String[] args) {
54         MyList queue = new MyList(6, 3);
55         Thread threadA = new Thread(new Runnable() {
56             @Override
57             public void run() {
58                 while (true) {
59                     queue.add();
60                 }
61             }
62         });
63         Thread threadB = new Thread(new Runnable() {
64 
65             @Override
66             public void run() {
67                 while (true) {
68                     queue.take();
69                 }
70             }
71         });
72 
73         Thread threadC = new Thread(new Runnable() {
74 
75             @Override
76             public void run() {
77                 while (true) {
78                     System.out.println((queue.count));
79                 }
80             }
81         });
82 
83         threadB.start();
84         threadA.start();
85         threadC.start();
86     }
87 }

每个锁对象有两个队列,一个就绪队列,一个阻塞队列。就绪队列中线程已被唤醒,等待获得cpu,阻塞队列执行了wait(),等待被唤醒。

需要注意的是:

1. notify()通知过早,线程不会被唤醒,因为wait()后于notify()执行。

2. wait等待条件发生了变化,线程也不会被唤醒。 

3. 唤醒同类,线程陷入假死。如:生产者唤醒生产者,消费者唤醒消费者。

原文地址:https://www.cnblogs.com/wfq9330/p/8663435.html