博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Thread之三:Thread Join()的用法
阅读量:6993 次
发布时间:2019-06-27

本文共 4579 字,大约阅读时间需要 15 分钟。

 一、join用法

join()和wait()不会释放锁,join()是Thread的方法,wait()是Object的方法

 1.join方法定义在Thread类中,则调用者必须是一个线程

例如:

Thread t = new CustomThread();//这里一般是自定义的线程类t.start();//线程起动t.join();//此处会抛出InterruptedException异常

2.上面的两行代码也是在一个线程里面执行的

以上出现了两个线程,一个是我们自定义的线程类,我们实现了run方法,做一些我们需要的工作;另外一个线程,生成我们自定义线程类的对象,然后执行

customThread.start();customThread.join();

在这种情况下,两个线程的关系是一个线程由另外一个线程生成并起动,所以我们暂且认为第一个线程叫做“子线程”,另外一个线程叫做“主线程”。

二、为什么要用join()方法

主线程生成并启动了子线程,而子线程里要进行大量的耗时的运算(这里可以借鉴下线程的作用),当主线程处理完其他的事务后,需要用到子线程的处理结果,这个时候就要用到join();方法了。

三、join方法的作用

在网上看到有人说“将两个线程合并”。这样解释我觉得理解起来还更麻烦。不如就借鉴下API里的说法:

“等待该线程终止。”

解释一下,是主线程等待子线程的终止。也就是说主线程的代码块中,如果碰到了t.join()方法,此时主线程需要等待(阻塞),等待子线程结束了(Waits for this thread to die.),才能继续执行t.join()之后的代码块。

四、示例

class BThread extends Thread {    public BThread() {        super("[BThread] Thread");    };    public void run() {        String threadName = Thread.currentThread().getName();        System.out.println(threadName + " start.");        try {            for (int i = 0; i < 5; i++) {                System.out.println(threadName + " loop at " + i);                Thread.sleep(1000);            }            System.out.println(threadName + " end.");        } catch (Exception e) {            System.out.println("Exception from " + threadName + ".run");        }    }}class AThread extends Thread {    BThread bt;    public AThread(BThread bt) {        super("[AThread] Thread");        this.bt = bt;    }    public void run() {        String threadName = Thread.currentThread().getName();        System.out.println(threadName + " start.");        try {            bt.join();            System.out.println(threadName + " end.");        } catch (Exception e) {            System.out.println("Exception from " + threadName + ".run");        }    }}public class TestDemo {    public static void main(String[] args) {        String threadName = Thread.currentThread().getName();        System.out.println(threadName + " start.");        BThread bt = new BThread();        AThread at = new AThread(bt);        try {            bt.start();            Thread.sleep(2000);            at.start();            at.join();        } catch (Exception e) {            System.out.println("Exception from main");        }        System.out.println(threadName + " end!");    }}

结果:

main start.    //主线程起动,因为调用了at.join(),要等到at结束了,此线程才能向下执行。 [BThread] Thread start. [BThread] Thread loop at 0 [BThread] Thread loop at 1 [AThread] Thread start.    //线程at启动,因为调用bt.join(),等到bt结束了才向下执行。 [BThread] Thread loop at 2 [BThread] Thread loop at 3 [BThread] Thread loop at 4 [BThread] Thread end. [AThread] Thread end.    // 线程AThread在bt.join();阻塞处启动,向下继续执行的结果 main end!      //线程AThread结束,此线程在at.join();阻塞处启起动,向下继续执行的结果。

修改一下代码:

public class TestDemo {    public static void main(String[] args) {        String threadName = Thread.currentThread().getName();        System.out.println(threadName + " start.");        BThread bt = new BThread();        AThread at = new AThread(bt);        try {            bt.start();            Thread.sleep(2000);            at.start();            //at.join(); //在此处注释掉对join()的调用        } catch (Exception e) {            System.out.println("Exception from main");        }        System.out.println(threadName + " end!");    }}

结果:

main start.    // 主线程起动,因为Thread.sleep(2000),主线程没有马上结束;[BThread] Thread start.    //线程BThread起动[BThread] Thread loop at 0[BThread] Thread loop at 1main end!   // 在sleep两秒后主线程结束,AThread执行的bt.join();并不会影响到主线程。[AThread] Thread start.    //线程at起动,因为调用了bt.join(),等到bt结束了,此线程才向下执行。[BThread] Thread loop at 2[BThread] Thread loop at 3[BThread] Thread loop at 4[BThread] Thread end.    //线程BThread结束了[AThread] Thread end.    // 线程AThread在bt.join();阻塞处起动,向下继续执行的结果

五、从源码看join()方法

在AThread的run方法里,执行了bt.join();,进入看一下它的JDK源码:

public final void join() throws InterruptedException {    join(0L);}
public final synchronized void join(long l)        throws InterruptedException    {        long l1 = System.currentTimeMillis();        long l2 = 0L;        if(l < 0L)            throw new IllegalArgumentException("timeout value is negative");        if(l == 0L)            for(; isAlive(); wait(0L));        else            do            {                if(!isAlive())                    break;                long l3 = l - l2;                if(l3 <= 0L)                    break;                wait(l3);                l2 = System.currentTimeMillis() - l1;            } while(true);    }

Join方法实现是通过wait(小提示:Object 提供的方法)。 当main线程调用t.join时候,main线程会获得线程对象t的锁(wait 意味着拿到该对象的锁),调用该对象的wait(等待时间),直到该对象唤醒main线程 ,比如退出后。这就意味着main 线程调用t.join时,必须能够拿到线程t对象的锁。

 

转载地址:http://pybvl.baihongyu.com/

你可能感兴趣的文章
大白话5分钟带你走进人工智能-第二十五节决策树系列之信息增益和信息增益率(4)...
查看>>
【datamining】OLTP,OLAP,维度数据库,事实表,维度表、星形和雪花模式、数据立方体、概念分层...
查看>>
PIE SDK 距离分类和最大似然分类
查看>>
Add、Commit和Push
查看>>
NPInter数据集的奇葩标号的出坑秘籍
查看>>
Angular2地图的使用、地图画线、高德底图切换、图标变换等
查看>>
opencv Mat.at
查看>>
Android中android:visibility的3中属性的剖析
查看>>
SharePoint 客户端对象模型 多选查阅项赋值
查看>>
spring前两天复习
查看>>
动手动脑
查看>>
网络流(二)最大流的增广路算法
查看>>
IIS负载均衡-Application Request Route详解第四篇:使用ARR实现三层部署架构(转载)...
查看>>
TList To DataTable
查看>>
Cache.Insert 方法(摘自MSDN)
查看>>
Duck typing
查看>>
每日一记--索引/过滤器
查看>>
Struts2的CRUD操作
查看>>
A Simple Problem with Integers
查看>>
WampServer中MySQL中文乱码解决
查看>>