Java 并发编程笔记
原创...大约 2 分钟
Thread.join()
cThread.join()
方法使当前线程阻塞,直到子线程cThread
执行完毕后,当前线程才会恢复运行。
实现原理:
join()
方法调用了join(0)
public final void join() throws InterruptedException { join(0); }
join(long millis)
是一个同步方法,最后会通过调用wait()
方法挂起当前线程(即调用线程
),直到其他线程调用子线程cThread
的notify()
或者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; } } }
子线程
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 并发编程笔记》
本文地址: https://jixiaoyong.github.io/blog/posts/b4abf652.html
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 许可协议。转载请注明出处!