AI智能
改变未来

wait()与notify()


一,前言

​ 简单画了一下线程的流程图,只是一个大概。如图所示,线程有多种状态,那么不同状态之间是如何切换的,下面主要总结关于wait()和notify()的使用。

二,wait()

​ wait()和notify()都是定义在Object类中,为什么如此设计。因为synchronized中的这把锁可以是任意对象,所以任意对象都可以调用wait()和notify(),并且只有同一把锁才能对线程进行操作,不同锁之间是不可以相互操作的,所以wait和notify属于Object。请看如下API文档说明。

​ wait()提供三种构造方法,但前两种最为常用,wait()是让线程一直处于等待状态,直到手动唤醒,而wait(long timeout)可以指定等待时间,之后会自动唤醒。

​ 调用wait方法可以让当前线程进入等待唤醒状态,该线程会处于等待唤醒状态直到另一个线程调用了object对象的notify方法或者notifyAll方法。

三,notify()

​ notify()唤醒等待的线程,如果监视器种只有一个等待线程,使用notify()可以唤醒。但是如果有多条线程notify()是随机唤醒其中一条线程,与之对应的就是notifyAll()就是唤醒所有等待的线程,请看下面实例代码。

​ 案例:定义两条线程,分别让其线程等待,及线程唤醒。

​ 1,定义线程。

public class SetTarget implements Runnable{private Demo demo;public SetTarget(Demo demo) {this.demo = demo;}@Overridepublic void run() {demo.set();}}

[/code]

public class GetTarget implements Runnable {private Demo demo;public GetTarget(Demo demo) {this.demo = demo;}@Overridepublic void run() {demo.get();}}

[/code]

​ 2,编写main方法。

public class Demo {// 定义一个信号量private volatile int signal;public static void main(String[] args) {Demo demo = new Demo();SetTarget set = new SetTarget(demo);GetTarget get = new GetTarget(demo);// 开启线程,new Thread(get).start();new Thread(get).start();new Thread(get).start();new Thread(get).start();try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}new Thread(set).start();}// set方法唤醒线程public synchronized void set() {signal = 1;// notify方法会随机叫醒一个处于wait状态的线程notify();// notifyAll叫醒所有的处于wait线程,争夺到时间片的线程只有一个//notifyAll();System.out.println(\"叫醒线程叫醒之后休眠开始...\");try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}}// get方法使线程进入等待状态public synchronized int get() {System.out.println(Thread.currentThread().getName() + \" 方法执行了...\");if (signal != 1) {try {wait();System.out.println(\"叫醒之后\");} catch (InterruptedException e) {e.printStackTrace();}}System.out.println(Thread.currentThread().getName() + \" 方法执行完毕...\");return signal;}}

[/code]

​ 3,运行结果。

​ 分析:一共开启了4个线程,当全部进入等待状态时,调用notify()方法唤醒线程,但很明显只唤醒了其中一条线程。右上角显示程序并没有停止,原因就是其他3条线程仍在处于等待状态。

​ 使用notifyAll()唤醒线程:

四,生产者-消费者模式

​ 生产者-消费者模式,生产者生产商品,然后通知消费者进行消费。

​ 1,定义生产者

public class Vendor {// 定义库存数量private int count;// 定义最大库存private final int MAX_COUNT = 10;public synchronized void production() {while (count >= MAX_COUNT) {try {System.out.println(Thread.currentThread().getName() + \"库存数量达到最大值,停止生产。\");// 此时生产线程全部进入等待状态wait();} catch (InterruptedException e) {e.printStackTrace();}}// 否则生产商品count++;System.out.println(Thread.currentThread().getName() + \"正在生产商品,当前库存为:\" + count);notifyAll();}public synchronized void consumers() {while (count <= 0) {try {System.out.println(Thread.currentThread().getName() + \"没有商品了,消费者处于等待状态...\");wait();} catch (InterruptedException e) {e.printStackTrace();}}count--;System.out.println(Thread.currentThread().getName() + \"正在消费,当前库存为:\" + count);notifyAll();}}

[/code]

​ 2,分别定义两条线程。

public class SetTarget implements Runnable {private Vendor vendor;public SetTarget(Vendor vendor) {this.vendor = vendor;}@Overridepublic void run() {while(true){vendor.production();try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}

[/code]

public class GetTarget implements Runnable {private Vendor vendor;public GetTarget(Vendor vendor) {this.vendor = vendor;}@Overridepublic void run() {while(true){vendor.consumers();try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}

[/code]

​ 3,主方法。

public class Demo {public static void main(String[] args) {Vendor vendor = new Vendor();SetTarget set = new SetTarget(vendor);GetTarget get = new GetTarget(vendor);// 开启线程生产商品new Thread(set).start();new Thread(set).start();new Thread(set).start();new Thread(set).start();// 开启消费者线程new Thread(get).start();}}

[/code]

​ 4,运行结果。

五,总结

​ 线程之间通信就做这么一个简单的总结,以上内容如有错误,欢迎留言指正。

感谢阅读!

转载于:https://www.cnblogs.com/fenjyang/p/11603229.html

赞(0) 打赏
未经允许不得转载:爱站程序员基地 » wait()与notify()