一、前言

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

public class Thread01 extends Thread{

    @Override
public void run() {
for(int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + "=" + i);
} }
}

  main线程中起两个线程

public class Test {
public static void main(String[] args) throws InterruptedException {
Thread01 thread01 = new Thread01();
Thread01 thread02 = new Thread01();
thread01.start();
thread02.start();
}
}

  结果:

Thread-1=0
Thread-0=0
Thread-0=1
Thread-0=2
Thread-1=1
Thread-0=3
Thread-1=2
Thread-0=4
Thread-1=3
Thread-1=4

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

public class Test {
public static void main(String[] args) throws InterruptedException {
Thread01 thread01 = new Thread01();
Thread01 thread02 = new Thread01();
thread01.start();
thread01.join();
System.out.println("main thread after join");
thread02.start();
}
}

  其他不变,看一下结果:

Thread-0=0
Thread-0=1
Thread-0=2
Thread-0=3
Thread-0=4
main thread after join
Thread-1=0
Thread-1=1
Thread-1=2
Thread-1=3
Thread-1=4

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

二、join()/join(long millis)

/**
* 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);
}

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

/**
* 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;
}
}
}

  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. 01-css的引入方式

    [转]01-css的引入方式 引入css方式(重点掌握) 行内样式 内接样式 外接样式 3.1 链接式 3.1 导入式 css介绍 现在的互联网前端分三层: HTML:超文本标记语言.从语义的角度描述 ...

  2. linux内核调试技巧之一 dump_stack【转】

    在内核中代码调用过程难以跟踪,上下文关系复杂,确实让人头痛 调用dump_stack()就会打印当前cpu的堆栈的调用函数了. 如此,一目了然的就能看到当前上下文环境,调用关系了 假设: 遇到uvc_ ...

  3. java每日一总结

    一, 1.安装jdk时路径中不能有空格或者中文. 二, 1.进入文件夹:cd+文件夹名称. 2.进入多级文件夹:cd+文件夹1\文件夹2\文件夹3. 3.返回上一级:cd 空格+... 4.返回根路径 ...

  4. 目录命令(RD)

    RD命令: // 描述: 删除目录或子目录.同 rmdir // 语法: rd [<drive:>]<path> /s /q /? // 参数: /s: (subdirecto ...

  5. Ubuntu 16.04 启用 点击Launcher图标,窗口实现最小化 功能

    安装了Ubuntu之后,要是每次都点击最小化按钮来实现窗口的最小化,操作起来很不方便,那么怎么样才能方便操作呢, Ubuntu 16.04 本身支持 点击应用程序Launcher图标实现最小化 功能, ...

  6. 数据库连接池性能比对(hikari druid c3p0 dbcp jdbc)

    https://blog.csdn.net/qq_31125793/article/details/51241943 背景 对现有的数据库连接池做调研对比,综合性能,可靠性,稳定性,扩展性等因素选出推 ...

  7. Extending the Yahoo! Streaming Benchmark

    could accomplish with Flink back at Twitter. I had an application in mind that I knew I could make m ...

  8. poj 3090 Visible Lattice Points(离线打表)

    这是好久之前做过的题,算是在考察欧拉函数的定义吧. 先把欧拉函数讲好:其实欧拉函数还是有很多解读的.emmm,最基础同时最重要的算是,¢(n)表示范围(1, n-1)中与n互质的数的个数 好了,我把规 ...

  9. 【转】Android辅助功能AccessibilityService自动全选择文字粘贴模拟输入

    网上找了很久AccessibilityService全选文字的方法,一直没找到,自己研究了半天,分享出来. /** * 输入文本 */ public void inputText(List<St ...

  10. error C2381: “exit”: 重定义;__declspec(noreturn) 不同

    问题: error C2381: “exit” : 重定义:__declspec(noreturn) 不同 解决办法: 调换一下头文件的包含次序: #include <GL/glut.h> ...