当多个线程可以一起工作去解决某个问题时,如果某些部分必须在其它部分之前完成,那么就需要对线程进行协调。

join()

在线程中调用另一个线程的 join() 方法,会将当前线程挂起,而不是忙等待,直到目标线程结束。

对于以下代码,虽然 b 线程先启动,但是因为在 b 线程中调用了 a 线程的 join() 方法,b 线程会等待 a 线程结束才继续执行,因此最后能够保证 a 线程的输出先于 b 线程的输出。

public class JoinExample {private class A extends Thread {@Overridepublic void run() {System.out.println("A");}}private class B extends Thread {private A a;B(A a) {this.a = a;}@Overridepublic void run() {try {a.join();} catch (InterruptedException e) {e.printStackTrace();}System.out.println("B");}}public void test() {A a = new A();B b = new B(a);b.start();a.start();}
}
public static void main(String[] args) {JoinExample example = new JoinExample();example.test();
}

输出

A
B

wait() notify() notifyAll()

调用 wait() 使得线程等待某个条件满足,线程在等待时会被挂起,当其他线程的运行使得这个条件满足时,其它线程会调用 notify() 或者 notifyAll() 来唤醒挂起的线程。

它们都属于 Object 的一部分,而不属于 Thread。

只能用在同步方法或者同步控制块中使用,否则会在运行时抛出 IllegalMonitorStateException。

使用 wait() 挂起期间,线程会释放锁。这是因为,如果没有释放锁,那么其它线程就无法进入对象的同步方法或者同步控制块中,那么就无法执行 notify() 或者 notifyAll() 来唤醒挂起的线程,造成死锁。

public class WaitNotifyExample {public synchronized void before() {System.out.println("before");notifyAll();}public synchronized void after() {try {wait();} catch (InterruptedException e) {e.printStackTrace();}System.out.println("after");}
}
public static void main(String[] args) {ExecutorService executorService = Executors.newCachedThreadPool();WaitNotifyExample example = new WaitNotifyExample();executorService.execute(() -> example.after());executorService.execute(() -> example.before());
}

输出

before
after

wait() 和 sleep() 的区别

  • wait() 是 Object 的方法,而 sleep() 是 Thread 的静态方法;
  • wait() 会释放锁,sleep() 不会。

await() signal() signalAll()

java.util.concurrent 类库中提供了 Condition 类来实现线程之间的协调,可以在 Condition 上调用 await() 方法使线程等待,其它线程调用 signal() 或 signalAll() 方法唤醒等待的线程。

相比于 wait() 这种等待方式,await() 可以指定等待的条件,因此更加灵活。

使用 Lock 来获取一个 Condition 对象。

public class AwaitSignalExample {private Lock lock = new ReentrantLock();private Condition condition = lock.newCondition();public void before() {lock.lock();try {System.out.println("before");condition.signalAll();} finally {lock.unlock();}}public void after() {lock.lock();try {condition.await();System.out.println("after");} catch (InterruptedException e) {e.printStackTrace();} finally {lock.unlock();}}
}
public static void main(String[] args) {ExecutorService executorService = Executors.newCachedThreadPool();AwaitSignalExample example = new AwaitSignalExample();executorService.execute(() -> example.after());executorService.execute(() -> example.before());
}

输出

before
after

Java线程之间的协作相关推荐

  1. 线程的状态转换、sleep()、wait()、yeild()、终止线程的方法、线程之间的协作(join()、wait() notify() notifyAll()、await() signal() )

    1.线程的状态转换 1.1 新建(New) 创建后尚未启动 1.2 可运行(Runnable) 可能正在运行,也可能正在等待 CPU 时间片. 包含了操作系统线程状态中的 Running 和 Read ...

  2. Java 线程之间通信

    目录 概念 原理 实现 1. 第一种解法,包含多种小的不同实现方式,但一个共同点就是靠一个共享变量来做控制: a. 利用最基本的synchronized.notify.wait: b. 利用Lock和 ...

  3. Java线程之间通信

    用多线程的目的:更好的利用CPU的资源.因为所有的多线程代码都可以用单线程来实现. 多线程:指的是这个程序(一个进程)运行时产生了不止一个线程. 并行:多个CPU实例或者多台机器同时执行一段处理逻辑, ...

  4. 多线程:线程之间的协作(join、wait、notify、notifyAll、await、signal、signalAll)

    当多个线程可以一起工作去解决某个问题时,如果某些部分必须在其它部分之前完成,那么就需要对线程进行协调. join() 在线程中调用另一个线程的 join() 方法,会将当前线程挂起,而不是忙等待,直到 ...

  5. 黑马程序员————java线程之间的通信

    ------<a href="http://www.itheima.com" target="blank">Java培训.Android培训.iOS ...

  6. JAVA线程之间的通信

    原理 线程的通信可以被定义为:当多个线程共同操作共享的资源时,线程间通过某种方式互相告知自己的状态,以避免无效的资源争夺.线程间通信的方式可以有很多种:等待-通知.共享内存.管道流.每种方式用不同的方 ...

  7. Java线程详解(9)-并发协作

    Java线程:并发协作-生产者消费者模型 对于多线程程序来说,不管任何编程语言,生产者和消费者模型都是最经典的.就像学习每一门编程语言一样,Hello World!都是最经典的例子. 实际上,准确说应 ...

  8. java线程详解_Java线程详解

    程序.进程.线程的概念程序(program):是为完成特定任务.用某种语言编写的一组指令的集合.即指一段静态的代码,静态对象. 进程(process):是程序的一次执行过程,或是正在运行的一个程序.动 ...

  9. java线程-从生产者和消费者模型说起

    今天学习了经典的生产者和消费者模型,引起了对java线程等知识的一系列的思考. 在平时的编程中,经常遇到一个线程要产生数据,而另一个线程要处理产生出来的数据,这其实就是生产者和消费者的关系.生产者在产 ...

最新文章

  1. 如何快速评估16S rRNA基因引物的覆盖率及特异性
  2. 【JVM调优】JVM指令集大全
  3. 深入分析Flex [Bindable] (总结)
  4. php提交表单并发送邮件,php提交表单发送邮件的方法
  5. NMEA码详解【转】
  6. java 正负随机_如何产生一个随机的[0, n)范围内的Short值
  7. 第4届(2020)大学生集成电路创新创业大赛赛题分类
  8. stm32系统时钟配置,标准库v3.5
  9. Tomcat8安装步骤-win10-64位系统
  10. 如何将png图像转换成jpg格式呢?
  11. 国民生产总值饼状图_预期寿命和国内生产总值
  12. 计算机实践ps折扇,用PS打造一把水墨画折扇的教程
  13. STM32F401的RCC时钟配置
  14. 1980-2018年中国及世界各国实际利率数据
  15. 视频摘要和视频浓缩的区别
  16. WORD中如何删除掉某几页的页眉和页脚
  17. SSL/TLS会话的流量分析
  18. 2021-04-05 c++程序设计原理与实践持续学习笔记:第三章对象、类型和值。
  19. 常用查找法(C语言)
  20. ENC28J60学习笔记——第2部分

热门文章

  1. CodeForces 230A
  2. C#获取网上图片的宽高代码
  3. 软件设计师21-计算机体系结构
  4. [转]关于Python里的类型注解
  5. 通向财务自由之路06_适应大环境的交易策略
  6. 读书笔记_量化交易如何建立自己的算法交易01
  7. 离职潮来袭,但为什么HR还是很难招到人?
  8. FCKeditor插件开发
  9. AfxMessageBox
  10. 职称计算机 宜兴,关于报送2020年经济、石油化工工程、 电子信息工程和工艺美术高级专业技术资格评审材料的通知...