【Java并发编程篇】你知道 Java 是如何实现线程间通信的吗?
正常情况下,每个子线程完成各自的任务就可以结束了。不过有的时候,我们希望多个线程协同工作来完成某个任务,这时就涉及到了线程间通信了。
下面从几个例子作为切入点来讲解下 Java 里有哪些方法来实现线程间通信。
- 如何让两个线程依次执行?
- 那如何让 两个线程按照指定方式有序交叉运行呢?
- 四个线程 A B C D,其中 D 要等到 A B C 全执行完毕后才执行,而且 A B C 是同步运行的
- 三个运动员各自准备,等到三个人都准备好后,再一起跑
- 子线程完成某件任务后,把得到的结果回传给主线程
如何让两个线程依次执行?
有两个线程,线程A和线程B。线程B等线程A执行完后再执行。
可以使用在线程B中调用threadA.join()方法,线程B就会等待线程A执行完后再执行。
那如何让两个线程按照指定方式有序交叉运行呢?
利用 object.wait() 和 object.notify() 两个方法来实现。
四个线程 A B C D,其中 D 要等到 A B C 全执行完毕后才执行,而且 A B C 是同步运行的
利用 CountdownLatch 来实现。
基本用法是:
- 创建一个计数器,设置初始值,CountdownLatch countDownLatch = new CountDownLatch(3);
- 在 等待线程 里调用 countDownLatch.await() 方法,进入等待状态,直到计数值变成 0;
- 在 其他线程 里,调用 countDownLatch.countDown() 方法,该方法会将计数值减小 1;
- 当 其他线程 的 countDown() 方法把计数值变成 0 时,等待线程 里的 countDownLatch.await() 立即退出,继续执行下面的代码。
CountDownLatch 适用于一个线程去等待多个线程的情况。
三个运动员各自准备,等到三个人都准备好后,再一起跑
CountDownLatch 可以用来倒计数,但当计数完毕,只有一个线程的 await() 会得到响应,无法让多个线程同时触发。
为了实现线程间互相等待这种需求,我们可以利用 CyclicBarrier 数据结构,它的基本用法是:
- 先创建一个公共 CyclicBarrier 对象,设置 同时等待 的线程数,CyclicBarrier cyclicBarrier = new CyclicBarrier(3);
- 这些线程同时开始自己做准备,自身准备完毕后,需要等待别人准备完毕,这时调用 cyclicBarrier.await(); 即可开始等待别人;
- 当指定的 同时等待 的线程数都调用了 cyclicBarrier.await();时,意味着这些线程都准备完毕好,然后这些线程才 同时继续执行。
子线程完成某件任务后,把得到的结果回传给主线程
实际的开发中,我们经常要创建子线程来做一些耗时任务,然后把任务执行结果回传给主线程使用,这种情况在 Java 里要如何实现呢?
通过 FutureTask 和 Callable 可以直接在主线程获得子线程的运算结果,只不过需要阻塞主线程(futureTask.get() )。当然,如果不希望阻塞主线程,可以考虑利用 ExecutorService,把 FutureTask 放到线程池去管理执行。
参考: |