Java多线程中的wait、notify和park、unpark的使用详解
作者:小晨想好好学习
这篇文章主要介绍了Java多线程中的wait、notify和park、unpark的使用详解,它们都是线程之间进行协作的手段,都属于 Object 对象的方法,必须获得此对象的锁,才能调用这几个方法,需要的朋友可以参考下
一、wait & notify的使用
1、API介绍
- obj.wait() 让进入 object 监视器的线程到 waitSet 等待
- obj.wait(n) 让进入 object 监视器的线程到 waitSet 等待,n秒后还没有被唤醒的话,则自动醒来
- obj.notify() 在 object 上正在 waitSet 等待的线程中挑一个唤醒
- obj.notifyAll() 让 object 上正在 waitSet 等待的线程全部唤醒
它们都是线程之间进行协作的手段,都属于 Object 对象的方法。
必须获得此对象的锁,才能调用这几个方法 wait() 方法会释放对象的锁,进入 WaitSet 等待区,从而让其他线程就机会获取对象的锁。
无限制等待,直到notify 为止 wait(long n) 有时限的等待, 到 n 毫秒后结束等待,或是被 notify notify 只能随机唤醒一个 WaitSet 中的线程,这时如果有其它线程也在等待,那么就可能唤醒不了正确的线程,称之为【虚假唤醒】
2、demo
@Slf4j(topic = "c.TestCorrectPosture") public class TestCorrectPostureStep5 { static final Object room = new Object(); static boolean hasCigarette = false; static boolean hasTakeout = false; public static void main(String[] args) { new Thread(() -> { synchronized (room) { log.debug("有烟没?[{}]", hasCigarette); while (!hasCigarette) { log.debug("没烟,先歇会!"); try { room.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } log.debug("有烟没?[{}]", hasCigarette); if (hasCigarette) { log.debug("可以开始干活了"); } else { log.debug("没干成活..."); } } }, "小南").start(); new Thread(() -> { synchronized (room) { Thread thread = Thread.currentThread(); log.debug("外卖送到没?[{}]", hasTakeout); while (!hasTakeout) { log.debug("没外卖,先歇会!"); try { room.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } log.debug("外卖送到没?[{}]", hasTakeout); if (hasTakeout) { log.debug("可以开始干活了"); } else { log.debug("没干成活..."); } } }, "小女").start(); sleep(1); new Thread(() -> { synchronized (room) { hasTakeout = true; log.debug("外卖到了噢!"); room.notifyAll(); } }, "送外卖的").start(); } }
2、多线程模式
模式之保护性暂停 模式之生产者消费者
3、wait和notify的原理
二、Park & Unpark的使用
1、基本使用
它们是 LockSupport 类中的方法
// 暂停当前线程 LockSupport.park(); // 恢复某个线程的运行 LockSupport.unpark(暂停线程对象)
先 park 再 unpark
public static void main(String[] args) { Thread t1 = new Thread(() -> { log.debug("start..."); sleep(1); log.debug("park..."); LockSupport.park(); log.debug("resume..."); }, "t1"); t1.start(); sleep(4); log.debug("unpark..."); LockSupport.unpark(t1); }
先 unpark 再 park
public static void main(String[] args) { Thread t1 = new Thread(() -> { log.debug("start..."); sleep(2); log.debug("park..."); LockSupport.park(); log.debug("resume..."); }, "t1"); t1.start(); sleep(1); log.debug("unpark..."); LockSupport.unpark(t1); }
结论:park和unpark是成对出现,但是是不分先后的
2、特点
与 Object 的 wait & notify 相比
- wait,notify 和 notifyAll 必须配合 Object Monitor 一起使用,而 park,unpark 不必
- park & unpark 是以线程为单位来【阻塞】和【唤醒】线程(唤醒的时候可以传一个线程作为参数),而 notify 只能随机唤醒一个等待线程,notifyAll 是唤醒所有等待线程,就不那么【精确】
- park & unpark 可以先 unpark,而 wait & notify 不能先 notify
到此这篇关于Java多线程中的wait、notify和park、unpark的使用详解的文章就介绍到这了,更多相关Java多线程wait、notify和park内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!