一、前言

  通过一个简单的例子引入join()方法

  1. public class Thread01 extends Thread{
  2.  
  3. @Override
  4. public void run() {
  5. for(int i = 0; i < 5; i++) {
  6. System.out.println(Thread.currentThread().getName() + "=" + i);
  7. }
  8.  
  9. }
  10. }

  main线程中起两个线程

  1. public class Test {
  2. public static void main(String[] args) throws InterruptedException {
  3. Thread01 thread01 = new Thread01();
  4. Thread01 thread02 = new Thread01();
  5. thread01.start();
  6. thread02.start();
  7. }
  8. }

  结果:

  1. Thread-1=0
  2. Thread-0=0
  3. Thread-0=1
  4. Thread-0=2
  5. Thread-1=1
  6. Thread-0=3
  7. Thread-1=2
  8. Thread-0=4
  9. Thread-1=3
  10. Thread-1=4

  说明:可以看到,thread01和thread02并发执行,没有先后顺序,现在在thread01.start()之后加入join()方法

  1. public class Test {
  2. public static void main(String[] args) throws InterruptedException {
  3. Thread01 thread01 = new Thread01();
  4. Thread01 thread02 = new Thread01();
  5. thread01.start();
  6. thread01.join();
  7. System.out.println("main thread after join");
  8. thread02.start();
  9. }
  10. }

  其他不变,看一下结果:

  1. Thread-0=0
  2. Thread-0=1
  3. Thread-0=2
  4. Thread-0=3
  5. Thread-0=4
  6. main thread after join
  7. Thread-1=0
  8. Thread-1=1
  9. Thread-1=2
  10. Thread-1=3
  11. Thread-1=4

  说明:可以看到,thread01在调用join()后,会优先执行,等它执行完了,才会执行thread02。在分析main线程中的执行过程之前,先看一下join()方法的源码。

二、join()/join(long millis)

  1. /**
  2. * Waits for this thread to die.
  3. *
  4. * <p> An invocation of this method behaves in exactly the same
  5. * way as the invocation
  6. *
  7. * <blockquote>
  8. * {@linkplain #join(long) join}{@code (0)}
  9. * </blockquote>
  10. *
  11. * @throws InterruptedException
  12. * if any thread has interrupted the current thread. The
  13. * <i>interrupted status</i> of the current thread is
  14. * cleared when this exception is thrown.
  15. */
  16. public final void join() throws InterruptedException {
  17. join(0);
  18. }

  join()方法调用了join(long millis)方法

  1. /**
  2. * Waits at most {@code millis} milliseconds for this thread to
  3. * die. A timeout of {@code 0} means to wait forever.
  4. *
  5. * <p> This implementation uses a loop of {@code this.wait} calls
  6. * conditioned on {@code this.isAlive}. As a thread terminates the
  7. * {@code this.notifyAll} method is invoked. It is recommended that
  8. * applications not use {@code wait}, {@code notify}, or
  9. * {@code notifyAll} on {@code Thread} instances.
  10. *
  11. * @param millis
  12. * the time to wait in milliseconds
  13. *
  14. * @throws IllegalArgumentException
  15. * if the value of {@code millis} is negative
  16. *
  17. * @throws InterruptedException
  18. * if any thread has interrupted the current thread. The
  19. * <i>interrupted status</i> of the current thread is
  20. * cleared when this exception is thrown.
  21. */
  22. public final synchronized void join(long millis)
  23. throws InterruptedException {
  24. long base = System.currentTimeMillis();
  25. long now = 0;
  26.  
  27. if (millis < 0) {
  28. throw new IllegalArgumentException("timeout value is negative");
  29. }
  30.  
  31. if (millis == 0) {
  32. while (isAlive()) {
  33. wait(0);
  34. }
  35. } else {
  36. while (isAlive()) {
  37. long delay = millis - now;
  38. if (delay <= 0) {
  39. break;
  40. }
  41. wait(delay);
  42. now = System.currentTimeMillis() - base;
  43. }
  44. }
  45. }

  join(long millis)是同步方法,该方法是通过循环判断线程的isAlive的值(调用join方法的线程)来调用wait方法。当有线程执行完了,notifyAll方法会被调用,使其他处于等待的线程开始执行。

  分析一下main方法中的执行过程。在main线程中,首先thread01依次调用start()-->join()-->join(0)方法,因为join(long millis)是同步方法,main线程会去获取与thread01对象关联的monitor的所有权(The thread that executes monitorenter attempts to gain ownership of the monitor associated with objectref),thread01对象关联的monitor还没有被别的线程所有,所以main线程进入该同步方法,传入的参数millis为0,接着判断thread01线程isAlive(Tests if this thread is alive. A thread is alive if it has been started and has not yet died),为true,调用wait()方法,main线程处于等待状态,而thread01线程继续执行,当thread01线程执行完毕,join(long millis)方法结束,notifyAll()方法会被调用,main线程被唤醒,继续执行,打印出"main thread after join"语句,执行thread02线程。

Java多线程10:join()方法的更多相关文章

  1. Java多线程学习——join方法的使用

    join在线程里面意味着“插队”,哪个线程调用join代表哪个线程插队先执行——但是插谁的队是有讲究了,不是说你可以插到队头去做第一个吃螃蟹的人,而是插到在当前运行线程的前面,比如系统目前运行线程A, ...

  2. 转载:Java多线程中join方法的理解

    转载自:http://uule.iteye.com/blog/1101994 thread.Join把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程.比如在线程B中调用了线程A ...

  3. Java多线程中join方法详解

    join()方法用于让当前执行线程等待join线程执行结束.其实现原理是不停的检查join线程是否存活,如果join线程存活则让当前线程永远等待. join()方法部分实现细节 while(isAli ...

  4. Java多线程中join方法的理解

    thread.Join把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程.比如在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继续执行线程B. t.join( ...

  5. 几周内搞定Java的10个方法

    不要将Java与JavaScript弄混了,Java的目标是“一次编译,到处调试”(呃,不对,是“到处运行”).简单来说,就是Java程序可以直接在任何设备上运行. Java语言是什么? 不管我们是否 ...

  6. Java多线程中join、yield、sleep方法详解

    在Java多线程编程中,Thread类是其中一个核心和关键的角色.因此,对该类中一些基础常用方法的理解和熟练使用是开发多线程代码的基础.本篇主要总结一下Thread中常用的一些静态方法的含义及代码中的 ...

  7. 并发编程之多线程基础-join方法及优先级(五)

    join()方法作用 当在主线程当中执行到t1.join()方法时,就认为主线程应该把执行权让给t1 优先级 现代操作系统基本采用时分的形式调度运行的线程,线程分配得到的时间片的多少决定了线程使用处理 ...

  8. java多线程10:并发工具类CountDownLatch、CyclicBarrier和Semaphore

    在JDK的并发包(java.util.concurrent下)中给开发者提供了几个非常有用的并发工具类,让用户不需要再去关心如何在并发场景下写出同时兼顾线程安全性与高效率的代码. 本文分别介绍Coun ...

  9. JAVA多线程---wait() & join()

    题外话: interrupt()方法  并不能中断一个正常运行的线程!!! class myThread extends Thread{ @Override public void run(){ fo ...

随机推荐

  1. Spring webflux

    Spring-webflux Spring 5.0 Spring-webflux 是一个全新的非堵塞的函数式 Reactive Web 框架,可以用来构建异步的.非堵塞的.事件驱动的服务. sprin ...

  2. 如何使用纯CSS制作特效导航条?

    先上张图,如何使用纯 CSS 制作如下效果? 在继续阅读下文之前,你可以先缓一缓.尝试思考一下上面的效果或者动手尝试一下,不借助 JS ,能否巧妙的实现上述效果. OK,继续.这个效果是我在业务开发的 ...

  3. arcgis api 3.x for js 入门开发系列八聚合效果(附源码下载)

    前言 关于本篇功能实现用到的 api 涉及类看不懂的,请参照 esri 官网的 arcgis api 3.x for js:esri 官网 api,里面详细的介绍 arcgis api 3.x 各个类 ...

  4. Apex 中的自定义迭代器

    迭代器 迭代器(iterator)可以遍历一个集合变量中的每个元素.Apex提供了Iterator接口来让开发者实现自定义的迭代器. Iterator接口 Iterator接口定义了两个函数: has ...

  5. Xamarin 学习笔记 - Page(页面)

    本文翻译自CodeProject文章:https://www.codeproject.com/Articles/1226447/Xamarin-Notes-Xamarin-Forms-Pages 转载 ...

  6. PHP技能树

  7. 监控 redis 执行命令

    监控 redis 执行命令 Intro 最近在用 redis 的时候想看看执行了哪些命令,于是发现了 redis-cli 提供的 Monitor 命令,直接使用这个就可以监控执行的大部分 redis ...

  8. 【原】Java学习笔记004 - 运算符

    package cn.temptation; public class Sample01 { public static void main(String[] args) { // 运算符:对常量 或 ...

  9. windows批处理添加AD域账户

    因为要用个批处理命令在Windows Server里面批量添加域用户,所以需要使用批处理命令. 我这篇是纯新手教程,在百度上搜了一些批处理命令感觉属于进阶教程,研究了两天才完成我要完成的目标. 下面从 ...

  10. Kafka 0.11.0.0 实现 producer的Exactly-once 语义(官方DEMO)

    <dependency> <groupId>org.apache.kafka</groupId> <artifactId>kafka-clients&l ...