Java 中 Thread 的 join 方法
Java juc 面试 About 5,248 words介绍
Waits for this thread to die.
join()
方法上的注释是等待该线程销毁。
t1.join()
表示等待t1
线程执行完成,继续执行后续代码。
假设调用t1.join()
的地方在主线程,那么主线程就会等待t1
线程执行完后,继续执行主线程中的后续代码。
示例代码
public class ThreadJoinDemo {
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
System.out.println(LocalDateTime.now() + " t1 is running, group#" + Thread.currentThread().getThreadGroup());
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "t1");
Thread t2 = new Thread(() -> {
try {
//t1调用join方法, t2会等待t1运行完之后才会开始执行后续代码
t1.join();
System.out.println(LocalDateTime.now() + " t2 is running, group#" + Thread.currentThread().getThreadGroup());
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "t2");
Thread t3 = new Thread(() -> {
try {
//t2调用join方法, t3会等待t2运行完之后才会开始执行后续代码
t2.join();
System.out.println(LocalDateTime.now() + " t3 is running, group#" + Thread.currentThread().getThreadGroup());
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "t3");
//依次启动3个线程
t1.start();
t2.start();
t3.start();
}
}
输出:
2021-04-06T16:09:06.087 t1 is running, group#java.lang.ThreadGroup[name=main,maxpri=10]
2021-04-06T16:09:09.102 t2 is running, group#java.lang.ThreadGroup[name=main,maxpri=10]
2021-04-06T16:09:10.103 t3 is running, group#java.lang.ThreadGroup[name=main,maxpri=10]
源码分析
join()
在调用时wait()
等待线程执行完成后,底层C++
代码在线程结束后自动调用JavaThread::exit
方法,唤醒线程。
public class Thread implements Runnable {
public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
}
private void init(ThreadGroup g, Runnable target, String name, long stackSize) {
init(g, target, name, stackSize, null, true);
}
private void init(ThreadGroup g, Runnable target, String name, long stackSize, AccessControlContext acc, boolean inheritThreadLocals) {
...
Thread parent = currentThread(); // new 该线程的线程,案例中是 main 线程
SecurityManager security = System.getSecurityManager();
if (g == null) {
// security 为 null
if (security != null) {
g = security.getThreadGroup();
}
// main 线程的用户组是 main
if (g == null) {
g = parent.getThreadGroup();
}
}
...
}
// 阻塞直到线程运行结束
public final void join() throws InterruptedException {
join(0);
}
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); // Object 的 wait 方法,阻塞在此
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
/**
* Tests if this thread is alive. A thread is alive if it has
* been started and has not yet died.
*
* 测试线程是否还存活。线程如果已启动或者未结束退出则还是存活状态。
*/
public final native boolean isAlive();
// 线程所属的组
private ThreadGroup group;
/**
* 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);
group = null;
}
target = null;
// 主动置为 null 加快内存释放
threadLocals = null;
inheritableThreadLocals = null;
inheritedAccessControlContext = null;
blocker = null;
uncaughtExceptionHandler = null;
}
}
public class ThreadGroup implements Thread.UncaughtExceptionHandler {
void threadTerminated(Thread t) {
synchronized (this) {
remove(t);
// 如果线程组中的线程为 0,则 notifyAll 唤醒所有线程
if (nthreads == 0) {
notifyAll();
}
if (daemon && (nthreads == 0) &&
(nUnstartedThreads == 0) && (ngroups == 0))
{
destroy();
}
}
}
}
线程在结束运行退出时,底层C++
调用线程notify_all
唤醒该线程上wait
的对象。
源码路径:openjdk\hotspot\src\share\vm\runtime\thread.cpp
。
#thread.cpp
//线程结束,调用该方法
void JavaThread::exit(bool destroy_vm, ExitType exit_type) {
...
ensure_join(this);
...
}
static void ensure_join(JavaThread* thread) {
...
ObjectLocker lock(threadObj, thread);
...
//唤醒等待在thread对象上的线程
lock.notify_all(thread);
...
}
#ObjectSynchronizer.hpp
void notify_all(TRAPS) { ObjectSynchronizer::notifyall(_obj, CHECK); }
Views: 2,434 · Posted: 2021-04-11
————        END        ————
Give me a Star, Thanks:)
https://github.com/fendoudebb/LiteNote扫描下方二维码关注公众号和小程序↓↓↓
Loading...