当前位置: 首页 > news >正文

异步回调之Join

join:异步阻塞之闷葫芦

阻塞模式实现泡茶实例首先从基础的多线程join合并实验入手.join操作的原理是阻塞当前线程,直到待合并的目标线程执行完成.

线程的合并流程

Java中线程的合并流程是:假设线程A调用线程B的join()方法去合并B线程,那么线程A进入阻塞状态,直到线程B执行完成.

泡茶例子中,主线程通过分别调用烧水线程和清洗线程的join()方法,等待烧水线程和清洗线程完成,然后主线程执行泡茶操作.流程参考图如下.

通过join()实现异步泡茶喝

通过join实现一个异步阻塞版本,参考如下.

public class JoinDemo {public static final int SLEEP_GAP = 500;public static String getCurrentThreadName() {return Thread.currentThread().getName();}static class HotWaterThread extends Thread {public HotWaterThread() {super("烧水--Thread");}@Overridepublic void run() {try {System.out.println("洗好水壶");System.out.println("灌上凉水");System.out.println("放在火上");Thread.sleep(SLEEP_GAP);System.out.println("水开了");} catch (InterruptedException e) {System.out.println("烧水失败");}System.out.println("运行结束");}}static class WashThread extends Thread {public WashThread() {super("清洗--Thread");}@Overridepublic void run() {try {System.out.println("洗茶壶");System.out.println("洗茶杯");System.out.println("拿茶叶");Thread.sleep(SLEEP_GAP);System.out.println("洗完了");} catch (InterruptedException e) {System.out.println("洗茶壶茶杯失败");}System.out.println("运行结束");}}public static void main(String[] args) {WashThread washThread = new WashThread();HotWaterThread hotWaterThread = new HotWaterThread();washThread.start();hotWaterThread.start();try {washThread.join();hotWaterThread.join();Thread.currentThread().setName("主线程");System.out.println("泡茶喝");} catch (InterruptedException e) {e.printStackTrace();}System.out.println(getCurrentThreadName() + "运行结束");}
}

程序中有三个线程:主线程main 烧水线程HotWaterThread 清洗线程WashThread,主线程调用了这两个线程的join方法进行合并.

Join()方法详解

join方法应用场景如下:

A线程调用B线程的join方法,等待B线程执行完成,在B线程没有完成之前,A线程阻塞.

Join()方法有三个重载版本:

    /*** Waits for this thread to die.** <p> An invocation of this method behaves in exactly the same* way as the invocation** <blockquote>* {@linkplain #join(long) join}{@code (0)}* </blockquote>** @throws  InterruptedException*          if any thread has interrupted the current thread. The*          <i>interrupted status</i> of the current thread is*          cleared when this exception is thrown.*/public final void join() throws InterruptedException {join(0);}

A线程等待B线程执行结束后,A线程重新开始执行. 

    /*** Counts the number of stack frames in this thread. The thread must* be suspended.** @return     the number of stack frames in this thread.* @exception  IllegalThreadStateException  if this thread is not*             suspended.* @deprecated The definition of this call depends on {@link #suspend},*             which is deprecated.  Further, the results of this call*             were never well-defined.*/@Deprecatedpublic native int countStackFrames();/*** Waits at most {@code millis} milliseconds for this thread to* die. A timeout of {@code 0} means to wait forever.** <p> This implementation uses a loop of {@code this.wait} calls* conditioned on {@code this.isAlive}. As a thread terminates the* {@code this.notifyAll} method is invoked. It is recommended that* applications not use {@code wait}, {@code notify}, or* {@code notifyAll} on {@code Thread} instances.** @param  millis*         the time to wait in milliseconds** @throws  IllegalArgumentException*          if the value of {@code millis} is negative** @throws  InterruptedException*          if any thread has interrupted the current thread. The*          <i>interrupted status</i> of the current thread is*          cleared when this exception is thrown.*/public final synchronized void join(long millis)throws InterruptedException {long base = System.currentTimeMillis();long now = 0;if (millis < 0) {throw new IllegalArgumentException("timeout value is negative");}if (millis == 0) {while (isAlive()) {wait(0);}} else {while (isAlive()) {long delay = millis - now;if (delay <= 0) {break;}wait(delay);now = System.currentTimeMillis() - base;}}}

A线程等待B线程执行一段时间,最长时间为millis 毫秒,超过后就会A线程重新执行.

    /*** Waits at most {@code millis} milliseconds plus* {@code nanos} nanoseconds for this thread to die.** <p> This implementation uses a loop of {@code this.wait} calls* conditioned on {@code this.isAlive}. As a thread terminates the* {@code this.notifyAll} method is invoked. It is recommended that* applications not use {@code wait}, {@code notify}, or* {@code notifyAll} on {@code Thread} instances.** @param  millis*         the time to wait in milliseconds** @param  nanos*         {@code 0-999999} additional nanoseconds to wait** @throws  IllegalArgumentException*          if the value of {@code millis} is negative, or the value*          of {@code nanos} is not in the range {@code 0-999999}** @throws  InterruptedException*          if any thread has interrupted the current thread. The*          <i>interrupted status</i> of the current thread is*          cleared when this exception is thrown.*/public final synchronized void join(long millis, int nanos)throws InterruptedException {if (millis < 0) {throw new IllegalArgumentException("timeout value is negative");}if (nanos < 0 || nanos > 999999) {throw new IllegalArgumentException("nanosecond timeout value out of range");}if (nanos >= 500000 || (nanos != 0 && millis == 0)) {millis++;}join(millis);}

A线程等待B线程执行一段时间,最长时间为millis 毫秒加nanos纳秒,超过后就会A线程重新执行.

容易混淆的几点.

join()是实例方法,不是静态方法.

调用join方法时,不是thread所指向的目标线程阻塞,而是当前线程被阻塞.

只有等待的thread执行完成或者超时,当前线程才能启动执行.

总结下,join方法通过上面的源码可以看出,是不断通过检查线程是否存存活,来进行阻塞.直到被唤醒才会解除阻塞.而且join方法不能拿到返回结果,缺少很多的灵活性.所以join更多的停留在Demo演示上.

坚持读书久了,会发现自己变得温文尔雅.技术坚持久了,理解也会越来越深.

多给自己一点坚持.云淡风轻 温文尔雅是由内而外的.

如果大家喜欢我的分析的话,可以关注下我的微信公众号

心有九月星辰


http://www.mrgr.cn/news/64317.html

相关文章:

  • 003-Kotlin界面开发之声明式编程范式
  • 录屏天花板,录课新玩法,人像+一切,PPT/PDF/视频/网页,也可即可录
  • Get包中的依赖管理介绍
  • StandardThreadExecutor源码解读与使用(tomcat的线程池实现类)
  • windows 11 配置 kafka 使用SASL SCRAM-SHA-256 认证
  • vscode在windows和linux如何使用cmake构建项目并make生成可执行文件,两者有什么区别
  • 第十七课 component组件解析
  • Rust语言有哪些常用语句?
  • zyb 的 Codeforces Round 983 (Div. 2)
  • WPF+MVVM案例实战(十八)- 自定义字体图标按钮的封装与实现(ABD类)
  • Python使用K-means实现文本聚类
  • Respiratory Physiology Neurobiology
  • TCP编程-socket(套接字)编程实战1
  • RK3568平台开发系列讲解(中断篇)延迟工作实验
  • vscode makfile编译
  • 电阻基础知识(六)-电阻的失效模式和失效机理
  • 【MacOS实操】如何基于SSH连接远程linux服务器
  • redis详细教程(7.哨兵)
  • 《GBDT 算法的原理推导》 11-13初始化模型 公式解析
  • LangChain学习之路
  • 【Comsol教程】计算流道中的流量
  • 一般无人机和FPV无人机的区别
  • WorkFlow Communicator之TCPServer(上)
  • QT打包Macosx应用发布App Store简易流程
  • 关于函数指针的一些例子说明
  • 探讨 Vue2 和 Vue3 中双向绑定机制的优化与差异