Thread中join方法的使用分析

来源:互联网 发布:网络舆情分析师待遇 编辑:程序博客网 时间:2024/06/16 12:21

一 Thread类的join方法作用分析

join有什么作用?我们先看一个例子:

新建一个线程:

package com.lanhuigu.JavaBase.thread.jointest;public class MyThread extends Thread{@Overridepublic void run() {// TODO Auto-generated method stubtry {int seconds = (int)(Math.random() * 10000);Thread.sleep(seconds);// 随机等待某端时间System.out.println("生成线程随机停止时间:" + seconds);} catch (InterruptedException ex) {// TODO: handle exceptionex.printStackTrace();}}}
测试方法:

package com.lanhuigu.JavaBase.thread.jointest;public class RunTest {public static void main(String[] args) {try {MyThread myThread = new MyThread();myThread.start();//myThread.join();myThread.sleep(1000);// 线程休眠某段时间,这个时间没发控制System.out.println("等myThread线程运行结束后,再执行!");} catch (InterruptedException ex) {// TODO: handle exceptionex.printStackTrace();}}}
我们在RunTest中使用myThread.sleep(1000)的目的是想让MyThread中run方法执行完之后,

再执行main方法中打印"等myThread线程运行结束后,再执行!",这样做会存在一个问题,

MyThread中的sleep()休眠时间是随机产生的,而main中的sleep()时间是无法具体某个时间的,

并不能保证每次都是MyThread执行完run后再执行main中的打印方法。


为了解决保证每次都是MyThread的run方法执行完成后,再执行main方法中的打印方法,

可以使用Thread类中的join()方法,join方法的作用如下:

使当前所属线程对象X中的run()正常执行任务,而使当前线程Y无限期进行阻塞,

等X销毁后再继续执行线程Y后面的代码。具有使线程排队运行的作用,具有同步的效果。


join()源码分析:

不传时间,源码默认为0毫秒, 再调用传时间的方法:

    public final void join() throws InterruptedException {        join(0);    }
调用传时间的方法,根据millis判断,包含是否传入时间的处理逻辑:
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;            }        }    }

从源码可以看出,while循环一直在检测是否有线程存活(X线程是否还在执行run方法),

如果有,就使当前线(Y线程)程调用wait方法处于等待,当while检测到无存活线程时(X线程销毁),

(Y线程)就不调用wait方法,当前线程(Y线程)也就马上恢复执行,因为等待时间为0。

当然了,如果传入具体join(long millis)等待时间,就是当线程结束(X线程销毁)时,

当前线程(Y线程)需要等待delay时间后恢复执行。

把上面的测试类myThread.sleep()方法修改为join方法(),修改后再执行,可以保证MyThread执行完后,main才打印数据。

修改后测试类:

package com.lanhuigu.JavaBase.thread.jointest;public class RunTest {public static void main(String[] args) {try {MyThread myThread = new MyThread();myThread.start();myThread.join();//myThread.sleep(1000);// 线程休眠某段时间,这个时间没发控制System.out.println("等myThread线程运行结束后,再执行!");} catch (InterruptedException ex) {// TODO: handle exceptionex.printStackTrace();}}}


二 join方法异常

当一个线程加入join后,再调用线程中断方法(interrupt),将会抛InterruptedException异常。

如果传入long millis不合法时,即传入负数时,将会抛IllegalArgumentException异常。