【线程基础】【四】join()方法详解

1  前言

看了wait()方法之后,我们再来讲讲join()方法,因为join()方法就是通过wait()方法实现的。

2  含义

让主线程等待(WAITING状态),一直等到其他线程不再活动为止。join在英语中是“加入”的意思,join()方法要做的事就是,当有新的线程加入时,主线程会进入等待状态,一直到调用join()方法的线程执行结束为止。

join用法示例:

public static void main(String[] args) {
    Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println("子线程执行");
            }
        };
    Thread thread1 = new Thread(runnable);
    Thread thread2 = new Thread(runnable);
    thread1.start();
    thread2.start();
    try {
        //主线程开始等待子线程thread1,thread2
        thread1.join();
        thread2.join();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    //等待两个线程都执行完(不活动)了,才执行下行打印
    System.out.println("执行完毕");
}

代码会在thread1和thread2执行完后,才会执行System.out.println("执行完毕");

3  源码

join()方法代码是通过java代码实现的,代码如下:

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) {
        // 关键实现在此行,通过wait方法永久等待。
        while (isAlive()) {
            wait(0);
        }
    } else {
        while (isAlive()) {
            long delay = millis - now;
            if (delay <= 0) {
                break;
            }
            wait(delay);
            now = System.currentTimeMillis() - base;
        }
    }
}

join()方法的等效写法:

thread1.join();
thread2.join();
// 可以替换为:
while (thread1.isAlive() || thread2.isAlive()) {
    //只要两个线程中有任何一个线程还在活动,主线程就不会往下执行
}

join()方法是用wait()方法实现,但为什么没有通过notify()系列方法唤醒呀,如果不唤醒,那不就一直等待下去了吗?

原因是:在java中,Thread类线程执行完run()方法后,一定会自动执行notifyAll()方法即Thread类线程执行完run()方法后,一定会自动执行notifyAll()方法,这个细节隐藏在Java的Native方法中,所以一般不会被人发现。我们观察C/C++源码,如下:

oid JavaThread::exit(booldestory_vm, ExitTypeexit_type);
static void ensure_join(JavaThread*thread) {
    Handle threadObj(thread, thread -> threadObj());
    ObjectLocker lock(threadObj, thread);
    thread -> clear_pending_exception();
    java_lang_Thread::set_thread_status(threadObj(), java_lang_Thread::TERMINATED);
    java_lang_Thread::set_thread(threadObj(), NULL);
     //下行执行了notifyAll()操作
    lock.notify_all(thread);
    thread -> clear_pending_exception();
}

其中ensure_join就是执行join()方法,等方法执行结束时,此行代码lock.notify_all(thread);意思是通过notifyAll()唤醒了所有等待线程。所以在使用线程的时候,要特别注意。

4  小结

好啦,关于join方法就看到这里,实际调用的是wait方法,有理解不对的地方欢迎指正哈。

 

posted @ 2023-04-18 08:05  酷酷-  阅读(583)  评论(0编辑  收藏  举报