作用:
主线程等待子线程执行完成后结束,join()的作用是等待线程对象的销毁
1、join中断
join期间主线程被中断则不会等待子线程执行完毕,所以应该在主线程被中断时调用interrupt方法中断子线程
package com.imooc.thread_demo.join;import lombok.Setter;/*** @Author: zhangjx* @Date: 2020/9/12 16:41* @Description:*/public class JoinInterrupt {public static void main(String[] args) {Thread thread = new Thread(new SubThread(Thread.currentThread()));thread.start();try {thread.join();} catch (InterruptedException e) {System.out.println("主线程被中断========");;thread.interrupt();}System.out.println("主线程运行完毕=========");}static class SubThread implements Runnable{private Thread mainThread;public SubThread(Thread mainThread) {this.mainThread = mainThread;}@Overridepublic void run() {try {mainThread.interrupt();Thread.sleep(5000);} catch (InterruptedException e) {System.out.println("子线程被中断=========");}System.out.println("子线程运行完毕======");}}}
此时主线程被中断后子线程也会被中断。
主线程被中断========主线程运行完毕=========子线程被中断=========子线程运行完毕======
2、join期间,主线程的状态
主线程运行状态为Waiting
package com.imooc.thread_demo.join;/*** @Author: zhangjx* @Date: 2020/9/12 17:39* @Description:*/public class JoinState {public static void main(String[] args) {Thread thread = new Thread(new SubThread(Thread.currentThread()));thread.start();try {thread.join();} catch (InterruptedException e) {System.out.println("主线程被中断========");;}System.out.println("主线程运行完毕=========");}static class SubThread implements Runnable{private Thread mainThread;public SubThread(Thread mainThread) {this.mainThread = mainThread;}@Overridepublic void run() {try {Thread.sleep(5000);System.out.println("主线程状态:" + mainThread.getState());} catch (InterruptedException e) {System.out.println("子线程被中断=========");}System.out.println("子线程运行完毕======");}}}
"C:\Program Files\Java\jdk1.8.0_171\bin\java.exe" "-javaagent:D:\idea2020\IntelliJ IDEA 2020.1.2\lib\idea_rt.jar=4155:D:\idea2020\IntelliJ IDEA 2020.1.2\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_171\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_171\jre\lib\rt.jar;C:\Users\z\Desktop\mooc\多线程\thread_demo\target\classes;E:\repository\org\springframework\boot\spring-boot-starter\2.2.2.RELEASE\spring-boot-starter-2.2.2.RELEASE.jar;E:\repository\org\springframework\boot\spring-boot\2.2.2.RELEASE\spring-boot-2.2.2.RELEASE.jar;E:\repository\org\springframework\spring-context\5.2.2.RELEASE\spring-context-5.2.2.RELEASE.jar;E:\repository\org\springframework\spring-aop\5.2.2.RELEASE\spring-aop-5.2.2.RELEASE.jar;E:\repository\org\springframework\spring-beans\5.2.2.RELEASE\spring-beans-5.2.2.RELEASE.jar;E:\repository\org\springframework\spring-expression\5.2.2.RELEASE\spring-expression-5.2.2.RELEASE.jar;E:\repository\org\springframework\boot\spring-boot-autoconfigure\2.2.2.RELEASE\spring-boot-autoconfigure-2.2.2.RELEASE.jar;E:\repository\org\springframework\boot\spring-boot-starter-logging\2.2.2.RELEASE\spring-boot-starter-logging-2.2.2.RELEASE.jar;E:\repository\ch\qos\logback\logback-classic\1.2.3\logback-classic-1.2.3.jar;E:\repository\ch\qos\logback\logback-core\1.2.3\logback-core-1.2.3.jar;E:\repository\org\apache\logging\log4j\log4j-to-slf4j\2.12.1\log4j-to-slf4j-2.12.1.jar;E:\repository\org\apache\logging\log4j\log4j-api\2.12.1\log4j-api-2.12.1.jar;E:\repository\org\slf4j\jul-to-slf4j\1.7.29\jul-to-slf4j-1.7.29.jar;E:\repository\jakarta\annotation\jakarta.annotation-api\1.3.5\jakarta.annotation-api-1.3.5.jar;E:\repository\org\springframework\spring-core\5.2.2.RELEASE\spring-core-5.2.2.RELEASE.jar;E:\repository\org\springframework\spring-jcl\5.2.2.RELEASE\spring-jcl-5.2.2.RELEASE.jar;E:\repository\org\yaml\snakeyaml\1.25\snakeyaml-1.25.jar;E:\repository\org\springframework\boot\spring-boot-devtools\2.2.2.RELEASE\spring-boot-devtools-2.2.2.RELEASE.jar;E:\repository\org\springframework\boot\spring-boot-configuration-processor\2.2.2.RELEASE\spring-boot-configuration-processor-2.2.2.RELEASE.jar;E:\repository\org\projectlombok\lombok\1.18.10\lombok-1.18.10.jar;E:\repository\org\slf4j\slf4j-api\1.7.29\slf4j-api-1.7.29.jar" com.imooc.thread_demo.join.JoinState主线程状态:WAITING子线程运行完毕======主线程运行完毕=========
3、join注意点
线程执行完毕后会主动调用notify_all方法,而join实质上就是使用wait()实现的,当子线程执行完毕唤醒主线程
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;}}}
join等价于
synichronized(thread.wait();){thread.wait();}
3.1 、CountDownLatch
3.2 、CyclicBarrier
