跳至主要內容

Java 并发编程笔记

JI,XIAOYONG...大约 2 分钟java

Thread.join()

cThread.join()方法使当前线程阻塞,直到子线程cThread执行完毕后,当前线程才会恢复运行。

实现原理:

  1. join()方法调用了join(0)

    public final void join() throws InterruptedException {
        join(0);
    }
    
  2. join(long millis)是一个同步方法,最后会通过调用wait()方法挂起当前线程(即调用线程),直到其他线程调用子线程cThreadnotify()或者notifyAll()方法

    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;
            }
        }
    }
    
  3. 子线程run()执行完毕后,系统在关闭该子线程前,会调用其exit()方法,继而在ThreadGroup.threadTerminated(Thread t)中唤醒被阻塞的调用线程。

    /**
     * This method is called by the system to give a Thread
     * a chance to clean up before it actually exits.
     */
    private void exit() {
        if (group != null) {
            group.threadTerminated(this);//提心 ThreadGroup 当前线程已经被终止
            group = null;
        }
    
        //其他代码 ……
    }
    
    // ThreadGroup
    void threadTerminated(Thread t) {
        synchronized (this) {
            remove(t);
    
            if (nthreads == 0) {//线程组线程数为0时
                notifyAll();//唤醒所有等待中的线程
            }
            if (daemon && (nthreads == 0) &&
                (nUnstartedThreads == 0) && (ngroups == 0))
            {
                destroy();
            }
        }
    }
    

notify() 和 notifyAll() 的区别区别

先了解两个概念:

锁池:某个Thread调用某个对象的同步方法(synchronized),但还没获取到该对象的锁时,会进入锁池和其他类似的线程一起竞争该对象的锁。

等待池:当某个Thread调用某个对象的wait()方法释放掉该对象的锁进入阻塞后(waiting on this object's monitor),会进入等待池。等待池中的线程不会竞争该对象的锁。

notify()方法会从等待池中唤醒一个指定线程,该线程可以再次回到锁池竞争该对象的锁,但可能会导致死锁(如果唯一唤醒的线程阻塞了并依赖其他线程唤醒,但其他线程都在等待池无法竞争锁,导致死锁)。

notifyAll()方法则会唤醒所有在等待池中的线程,之后他们都可以回到锁池竞争该对象的锁。

参考资料

Java Thread 的 join() 之刨根问底open in new window

java 中的 notify 和 notifyAll 有什么区别? - 大王叫我来巡山的回答 - 知乎open in new window

文章标题:《Java 并发编程笔记》
本文作者: JI,XIAOYONG
发布时间: 2019/10/28 18:26:46 UTC+8
更新时间: 2023/12/30 16:17:02 UTC+8
written by human, not by AI
本文地址: https://jixiaoyong.github.io/blog/posts/b4abf652.html
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 许可协议。转载请注明出处!
你认为这篇文章怎么样?
  • 0
  • 0
  • 0
  • 0
  • 0
  • 0
评论
  • 按正序
  • 按倒序
  • 按热度
Powered by Waline v2.15.8