线程间通信之等待唤醒机制
来源:互联网 发布:网络营销策划方案例文 编辑:程序博客网 时间:2024/05/15 07:05
线程间通信之等待唤醒机制
在命令式编程中,线程之间的通信机制有2种:共享内存和消息传递。
在共享内存的并发模型里,线程之间共享程序的公共状态,通过写-读内存中的公共状态进行隐式通信。在消息传递的并发模型里,线程之间内有公共状态,线程之间必须通过发送消息来进行显示通信。
等待唤醒机制
等待唤醒机制,是指一个线程A调用了对象Object的wait()
方法进入等待状态,而另一个线程B调用了对象Object的notify()
或者notifyAll()
方法,线程A收到了通知后,从对象Object的wait()
方法返回,进而执行后续操作。
上述两个线程通过Object对象来完成交互,而对象上的wait()
和notify()/notifyAll()
的关系就如同开关信号一样,用来完成等待方和通知方的交互工作。
等待/通知的相关方法是任意Java类对象都具备的,Object类都有实现
等待/通知的相关方法
notify()
: 通知一个对象上等待的线程,使其从wait()方法返回,而返回的前提是该线程获得了对象的锁。notifyAll()
:通知所有等待在该对象上的线程wait()
:调用该方法的线程进入等待状态,只有等待另外的线程的通知或被中断才会返回,需要注意,调用wait()方法后,会释放对象锁。wait(long mills)
:超时等待一段时间(单位毫秒),如果没有就超时返回。wait(long mills , int n)
:对超时时间更细粒度的控制,可以达到纳秒
调用wait()
和notify()/notifyAll()
需要注意的细节:
使用
wait()
和notify()/notifyAll()
时需要先对调用对象加锁。调用
wait()
方法后,线程状态由运行状态(Running)变为等待状态(Waiting),并将当前线程放置到对象的等待队列。notify()/notifyAll()
方法调用后,等待线程依旧不会从wait()返回,需要调用notify()/notifyAll()
的线程释放锁之后,等待线程才有机会从wait()返回。notify()
方法将等待队列中的一个等待线程移动到同步队列中,而notifyAll()
方法则是将等待队列中所有的线程全部移到同步队列,被移动的线程有等待状态(Waiting)变为阻塞状态(Blocked)。从
wait()
方法返回的前提是获得了调用对象的锁。
从上述细节中可以看到,等待唤醒机制依托于同步机制(同步对象锁),其目的就是确保wait()
方法返回时能够感应到通知线程对变量做出修改。
在Thread的API与wait()
有一个很像的方法sleep()
方法,他们2者的区别如下:
sleep()在休眠的过程中是一直持有锁的,而wait()是执行之后释放锁的。
等待/通知机制示例:
public class Test { private final static Object lock = new Object(); private static boolean flag = true; public static void main(String[] args) { ThreadA threadA = new ThreadA(); threadA.setName("threadA"); ThreadB threadB = new ThreadB(); threadB.setName("threadB"); threadA.start(); threadB.start(); } public static class ThreadA extends Thread { @Override public void run() { synchronized (lock) { while (flag) { System.out.println(getName() + ":开始执行"); try { System.out.println(getName() + ":进入等待状态"); lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(getName() + ":执行结束"); } } } public static class ThreadB extends Thread { @Override public void run() { synchronized (lock) { System.out.println(getName() + ":开始执行"); lock.notify(); System.out.println(getName() + ":通知释放锁"); flag = false; System.out.println(getName()+":执行结束"); } } }}
打印结果:
threadA:开始执行threadA:进入等待状态threadB:开始执行threadB:通知释放锁threadB:执行结束threadA:执行结束
在这个示例中,ThreadA和ThreadB的状态描述:
当ThreadA线程获取了lock对象锁,然后调用lock.wait()
方法。从而放弃了lock锁,ThraedA线程进入等待队列中(等待池),ThreadA进入等待状态。由于ThreadA释放了锁,此时ThreadB获得了lock锁,并调用notify()
方法,ThreadA从等待队列(等待池)进入同步队列(锁池),此时ThreadA由等待状态(Waiting)变为阻塞状态(Blocked)。ThreadB释放了lock锁后,ThreadA再次获取了lock锁,wait()
方法返回继续执行。
- 线程间通信之等待唤醒机制
- 线程间通信之等待唤醒机制
- Java线程间通信-等待唤醒机制
- 线程间通信--等待唤醒机制
- 线程间的通信------------等待唤醒机制
- java多线程——线程间通信之线程等待唤醒机制
- java基础12:线程间通信----等待唤醒机制
- 利用等待唤醒机制实现线程间的通信
- 线程间通信:生产者消费者(等待唤醒机制)
- Java多线程四:线程间通信/等待唤醒机制
- JavaSE 多线程 线程间通信— 等待唤醒机制
- 线程间通信、等待/唤醒机制的使用
- (51)线程间通信,等待唤醒机制
- java线程间通信——等待唤醒机制
- 线程之间的通信--等待唤醒机制
- 黑马程序员_JavaSE基础14 之 线程间通信 等待唤醒机制 多生产多消费者 ...
- java多线程之 生产者和消费者 线程间通信 等待与唤醒机制
- 多线程学习笔记(四)之线程间通信---等待唤醒机制
- mac终端下svn常用命令
- 计算机图形学
- selenium+robot+svn+jenkins自动化测试系列二:Jenkins配置自动化持续集成构建
- NAS资料收集
- Collections.sort()排序
- 线程间通信之等待唤醒机制
- 动态网页开发基础
- ZigBee3.0_JENNIC-JN516x-ZigBeeBaseDevice_20170605_1.1
- 2017.6.4 入门组 NO.1——k好数
- 检验两个线段是否相交
- BZOJ 1033: [ZJOI2008]杀蚂蚁antbuster
- 实验吧CTF逆向题1000writeup
- 使用Servlet Filter实现系统登录权限校验
- Kotlin基础教程-访问修饰符