【Java并发编程篇】你知道 Java 是如何实现线程间通信的吗?

正常情况下,每个子线程完成各自的任务就可以结束了。不过有的时候,我们希望多个线程协同工作来完成某个任务,这时就涉及到了线程间通信了。

下面从几个例子作为切入点来讲解下 Java 里有哪些方法来实现线程间通信。

  1. 如何让两个线程依次执行?
  2. 那如何让 两个线程按照指定方式有序交叉运行呢?
  3. 四个线程 A B C D,其中 D 要等到 A B C 全执行完毕后才执行,而且 A B C 是同步运行的
  4. 三个运动员各自准备,等到三个人都准备好后,再一起跑
  5. 子线程完成某件任务后,把得到的结果回传给主线程

如何让两个线程依次执行?

有两个线程,线程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 来实现。

基本用法是:

  1. 创建一个计数器,设置初始值,CountdownLatch countDownLatch = new CountDownLatch(3);
  2. 在 等待线程 里调用 countDownLatch.await() 方法,进入等待状态,直到计数值变成 0;
  3. 在 其他线程 里,调用 countDownLatch.countDown() 方法,该方法会将计数值减小 1;
  4. 当 其他线程 的 countDown() 方法把计数值变成 0 时,等待线程 里的 countDownLatch.await() 立即退出,继续执行下面的代码。

CountDownLatch 适用于一个线程去等待多个线程的情况。

三个运动员各自准备,等到三个人都准备好后,再一起跑

CountDownLatch 可以用来倒计数,但当计数完毕,只有一个线程的 await() 会得到响应,无法让多个线程同时触发。

为了实现线程间互相等待这种需求,我们可以利用 CyclicBarrier 数据结构,它的基本用法是:

  1. 先创建一个公共 CyclicBarrier 对象,设置 同时等待 的线程数,CyclicBarrier cyclicBarrier = new CyclicBarrier(3);
  2. 这些线程同时开始自己做准备,自身准备完毕后,需要等待别人准备完毕,这时调用 cyclicBarrier.await(); 即可开始等待别人;
  3. 当指定的 同时等待 的线程数都调用了 cyclicBarrier.await();时,意味着这些线程都准备完毕好,然后这些线程才 同时继续执行。

子线程完成某件任务后,把得到的结果回传给主线程

实际的开发中,我们经常要创建子线程来做一些耗时任务,然后把任务执行结果回传给主线程使用,这种情况在 Java 里要如何实现呢?

通过 FutureTask 和 Callable 可以直接在主线程获得子线程的运算结果,只不过需要阻塞主线程(futureTask.get() )。当然,如果不希望阻塞主线程,可以考虑利用 ExecutorService,把 FutureTask 放到线程池去管理执行。

 

参考:

 

posted @ 2021-12-19 13:31  残城碎梦  阅读(47)  评论(0编辑  收藏  举报