wait native 实现_Java并发编程笔记-线程协作之wait/notify/notifyAll,你会了吗?

我们知道,java里的线程是协作式的,在完成一项任务的过程中,因业务逻辑的需要,导致我们可能需要控制某些线程阻塞,等待另一些线程完成某部分事情后,再让线程继续执行。这个阻塞-唤醒的过程中就涉及到了线程之间的通信,也就是我接下来想说的多线程协作之等待-通知机制。java的Object类为我们提供一种实现等待-通知机制的方法,接下来了解一下wait/notify/notifyAll方法。

wait()、wait(long timeout)、wait(long timeout, int nanos)

打开Object类我们可以发现wait()和wait(long timeout, int nanos)实际上最终都会调用native方法wait(long timeout)。

wait()方法

5032b968e45341df8627e3018ef6496c

wait(long timeout, int nanos)方法

f419d3a6f3d747909d82594c2b42f499

wait(long timeout, int nanos)

重点看看native的wait(long timeout)方法。

03407b5e931d4b3988181860bc6e055d

从方法注释中我们至少可以得到三个结论:

  • wait方法导致当前线程阻塞直到有线程调用了该对象的notify/notifyAl方法或者线程中断;
  • 调用wait方法的线程必须持有对象的锁,否则抛出IllegalMonitorStateException;wait方法会释放锁,被唤醒后需重新竞争锁;
  • wait方法的使用方式模板如下
synchronized (obj){ while(condition does not hold){ obj.wait(); } // 业务逻辑} 

notify()、notifyAll()

notify方法

2f26eb30f902441d87bb48767f8503ac

可以从方法注释中得到3点结论:

  • notify唤醒的是任意一个在对象上等待的线程;
  • notify方法不释放锁,必须等当前线程执行完成释放锁后,wait的线程才能去竞争锁来执行;
  • 使用方式,需要在synchronized方法、synchronized静态方法、synchronized代码块中调用;

notifyAll方法,与notify类似,只不过notifyAll是唤醒在对象上等待的所有线程。

e6b74dcf9b0348e187afda1dc811988d

所以在使用过程中推荐尽量使用notifyAll,因为我们无法保证被唤醒的这个线程一定就是我们想要唤醒的线程。

基础用法,简单实现一个生产者消费者demo

public class ProducerAndConsumerDemo { static final int MAX_SIZE = 20; private static class ProduceThread implements Runnable { private final List produce; public ProduceThread(List produce) { this.produce = produce; } @Override public void run() { while (true) { synchronized (produce) { while (produce.size() == MAX_SIZE) { try { produce.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } if (produce.size() < MAX_SIZE) { int value = MAX_SIZE - produce.size(); produce.add(value); System.out.println(Thread.currentThread().getName() + "生产=" + value); produce.notifyAll(); } } } } } private static class ConsumeThread implements Runnable { private final List consume; public ConsumeThread(List consume) { this.consume = consume; } @Override public void run() { while (true) { synchronized (consume) { while (consume.isEmpty()) { try { consume.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } if (!consume.isEmpty()) { Integer remove = consume.remove(0); System.out.println(Thread.currentThread().getName() + "消费=" + remove); consume.notifyAll(); } } } } } public static void main(String[] args) { final List list = new ArrayList<>(); for (int i = 0; i < 1; i++) { new Thread(new ProduceThread(list)).start(); new Thread(new ConsumeThread(list)).start(); } }}
8d19b67860ff4d4eb271dc5131107537

若有失误之处,望请指正,感谢!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值