Wait&Notify的通知机制
wait表示线程的等待,调用该方法会导致线程阻塞,直至另一线程调用notify或notifyAll方法才可另其继续执行。经典的生产者、消费者模式即是使用wait/notify机制得以完成。
1.当线程A(消费者)调用wait()时,A会把锁释放出来,使自己进入等待状态,同时加入“锁对象”的等待队列。
2.线程B获取锁后,调用notify()通知“锁对象”的等待队列,使得线程A从等待队列进入阻塞队列。
3.线程A进入阻塞队列后,直到线程B释放锁,线程A竞争到锁之后才能继续执行wait()后的方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
| public class ThreadTest {
static final Object obj = new Object();
private static boolean flag = false;
public static void main(String[] args) throws Exception {
Thread consume = new Thread(new Consume(), "Consume"); Thread produce = new Thread(new Produce(), "Produce"); consume.start(); Thread.sleep(1000); produce.start();
try { produce.join(); consume.join(); } catch (InterruptedException e) { e.printStackTrace(); } }
static class Produce implements Runnable {
@Override public void run() {
synchronized (obj) { System.out.println("进入生产者线程"); System.out.println("生产"); try { TimeUnit.MILLISECONDS.sleep(2000); flag = true; obj.notify(); TimeUnit.MILLISECONDS.sleep(1000); System.out.println("退出生产者线程"); } catch (InterruptedException e) { e.printStackTrace(); } } } }
static class Consume implements Runnable {
@Override public void run() { synchronized (obj) { System.out.println("进入消费者线程"); System.out.println("wait flag 1:" + flag); while (!flag) { try { System.out.println("还没生产,进入等待"); obj.wait(); System.out.println("结束等待"); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("wait flag 2:" + flag); System.out.println("消费"); System.out.println("退出消费者线程"); }
} } }
|
输出结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| 进入消费者线程
wait flag 1:false
还没生产,进入等待
进入生产者线程
生产
退出生产者线程
结束等待
wait flag 2:true
消费
退出消费者线程
|
1.wait()
1
| public final void wait() throws InterruptedException,IllegalMonitorStateException
|
wait()用于把线程置于休眠状态,直至接到通知或被中断。
- 在调用wait()之前,线程必须获得对象“对象级别锁”,即只能在同步方法或者同步代码块中调用wait()。
- 进入wait()中,当前线程释放锁。
- 在从wait()返回前,除当前线程外的其他线程会竞争获得锁。
- 若没有竞争到适当的锁,则抛出IllegalMonitorStateException。
程便会处于该对象的等待池中,等待池中的线程不会去竞争该对象的锁。
2.notify()
1
| public final native void notify() throws IllegalMonitorStateException
|
该方法用来通知那些可能等待该对象的对象锁的其他线程(notify()方法用于通知调用wait()释放锁的线程从等待状态进入阻塞状态)。
- 如果有多个线程等待,则线程规划器任意挑选出其中一个wait()状态的线程来发出通知,并使它等待获取该对象的“对象锁”(就是获得了锁),别的线程不能访问它。
- 调用notify()方法后,当前线程不会马上释放该对象的锁,wait()所在的线程也不会马上获取该对象的锁,要等程序退出synchronized代码块后,当前线程才会释放锁,wait()所在的线程才能获得该对象锁。
???线程获得锁之后???