前言

简单记录一下Thread.join()的作用。

这里只是简单记录一下,方便自己回顾而已。

正文

join()是在Thread.java中定义

join源码

/**
 * Waits for this thread to die.[等待这个线程死亡]
 * @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(long millis)

public final void join(long millis)
throws InterruptedException {
    synchronized(lock) {
    long base = System.currentTimeMillis();
    long now = 0;
    if (millis < 0) {
        throw new IllegalArgumentException("timeout value is negative");
    }
    //如果传入0,就走这
    if (millis == 0) {
        //判断是否存活
        while (isAlive()) {
            //0时表示一直等待,直到notifyAll()或notify()通知
            lock.wait(0);
        }
    } else {
        while (isAlive()) {
            //倒计时
            long delay = millis - now;
            if (delay <= 0) {
                break;
            }
            //等待指定的时间
            lock.wait(delay);
            now = System.currentTimeMillis() - base;
        }
    }
    }
}
  1. 如果传入值millis为0时,需要等待线程死亡(任务结束)才会释放。

  2. 如果传入值millis大于0时,要么倒计时结束主动释放,要么线程死亡(任务结束),满足其一即可退出。

demo测试

下面简单的测试一下。先定义一个线程,如下。

private class MyThread extends Thread {
    public MyThread(String name) {
        setName(name);
    }

    @Override
    public void run() {
        super.run();
        Log.d(TAG, "name : " + getName() + " start ");
        for (int i = 0; i < 5; i++) {
            try {
                Log.d(TAG, "name : " + getName() + " [ " + i + " ] ");
                sleep(100);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        Log.d(TAG, "name : " + getName() + " end ");
    }
}
不使用join()
private void test() {
    MyThread myThreadA = new MyThread("Thread_A");
    myThreadA.start();
    Log.d(TAG, "name : " + Thread.currentThread().getName() + " start ");
    for (int i = 0; i < 5; i++) {
        Log.d(TAG, "name : " + Thread.currentThread().getName() + " [ " + i + " ] ");
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
    Log.d(TAG, "name : " + Thread.currentThread().getName() + " end ");
}

在main()中执行test()方法。执行后打印结果如下:

name : main start 
name : Thread_A start 
name : main [ 0 ] 
name : Thread_A [ 0 ] 
name : main [ 1 ] 
name : Thread_A [ 1 ] 
name : main [ 2 ] 
name : Thread_A [ 2 ] 
name : main [ 3 ] 
name : Thread_A [ 3 ] 
name : main [ 4 ] 
name : Thread_A [ 4 ] 
name : main end 
name : Thread_A end 

main线程和Thread_A一起抢占CPU资源的。

使用join()

下面代码是在上面基础上添加了join()方法,如下:

private void test() {
    MyThread myThreadA = new MyThread("Thread_A");
    myThreadA.start();
    //添加join()开始
    try {
        myThreadA.join();
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    }
    //添加join()结束
    Log.d(TAG, "name : " + Thread.currentThread().getName() + " start ");
    for (int i = 0; i < 5; i++) {
        Log.d(TAG, "name : " + Thread.currentThread().getName() + " [ " + i + " ] ");
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
    Log.d(TAG, "name : " + Thread.currentThread().getName() + " end ");
}

在main()中执行test()方法。执行后打印结果如下:

name : Thread_A start 
name : Thread_A [ 0 ] 
name : Thread_A [ 1 ] 
name : Thread_A [ 2 ] 
name : Thread_A [ 3 ] 
name : Thread_A [ 4 ] 
name : Thread_A end 
name : main start 
name : main [ 0 ] 
name : main [ 1 ] 
name : main [ 2 ] 
name : main [ 3 ] 
name : main [ 4 ] 
name : main end 

上面的打印顺序是有顺序了,都规规矩矩的。也就是CPU一直被Thread_A占用,main老老实实等着Thread_A死亡才可以抢CPU。

小结

  1. 调用join()的线程具有优先执行权。

  2. 当有线程调用join()后,其他线程会阻塞,直到调用join()线程死亡。

参考文章

  1. 《Java并发编程之美》

  2. 《Thread.java源码》

相关文章

暂无评论

none
暂无评论...