作用:
主线程等待子线程执行完成后结束,join()的作用是等待线程对象的销毁

1、join中断

join期间主线程被中断则不会等待子线程执行完毕,所以应该在主线程被中断时调用interrupt方法中断子线程

  1. package com.imooc.thread_demo.join;
  2. import lombok.Setter;
  3. /**
  4. * @Author: zhangjx
  5. * @Date: 2020/9/12 16:41
  6. * @Description:
  7. */
  8. public class JoinInterrupt {
  9. public static void main(String[] args) {
  10. Thread thread = new Thread(new SubThread(Thread.currentThread()));
  11. thread.start();
  12. try {
  13. thread.join();
  14. } catch (InterruptedException e) {
  15. System.out.println("主线程被中断========");;
  16. thread.interrupt();
  17. }
  18. System.out.println("主线程运行完毕=========");
  19. }
  20. static class SubThread implements Runnable{
  21. private Thread mainThread;
  22. public SubThread(Thread mainThread) {
  23. this.mainThread = mainThread;
  24. }
  25. @Override
  26. public void run() {
  27. try {
  28. mainThread.interrupt();
  29. Thread.sleep(5000);
  30. } catch (InterruptedException e) {
  31. System.out.println("子线程被中断=========");
  32. }
  33. System.out.println("子线程运行完毕======");
  34. }
  35. }
  36. }

此时主线程被中断后子线程也会被中断。

  1. 主线程被中断========
  2. 主线程运行完毕=========
  3. 子线程被中断=========
  4. 子线程运行完毕======

2、join期间,主线程的状态

主线程运行状态为Waiting

  1. package com.imooc.thread_demo.join;
  2. /**
  3. * @Author: zhangjx
  4. * @Date: 2020/9/12 17:39
  5. * @Description:
  6. */
  7. public class JoinState {
  8. public static void main(String[] args) {
  9. Thread thread = new Thread(new SubThread(Thread.currentThread()));
  10. thread.start();
  11. try {
  12. thread.join();
  13. } catch (InterruptedException e) {
  14. System.out.println("主线程被中断========");;
  15. }
  16. System.out.println("主线程运行完毕=========");
  17. }
  18. static class SubThread implements Runnable{
  19. private Thread mainThread;
  20. public SubThread(Thread mainThread) {
  21. this.mainThread = mainThread;
  22. }
  23. @Override
  24. public void run() {
  25. try {
  26. Thread.sleep(5000);
  27. System.out.println("主线程状态:" + mainThread.getState());
  28. } catch (InterruptedException e) {
  29. System.out.println("子线程被中断=========");
  30. }
  31. System.out.println("子线程运行完毕======");
  32. }
  33. }
  34. }
  1. "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
  2. 主线程状态:WAITING
  3. 子线程运行完毕======
  4. 主线程运行完毕=========

3、join注意点

线程执行完毕后会主动调用notify_all方法,而join实质上就是使用wait()实现的,当子线程执行完毕唤醒主线程

  1. public final synchronized void join(long millis)
  2. throws InterruptedException {
  3. long base = System.currentTimeMillis();
  4. long now = 0;
  5. if (millis < 0) {
  6. throw new IllegalArgumentException("timeout value is negative");
  7. }
  8. if (millis == 0) {
  9. while (isAlive()) {
  10. wait(0);
  11. }
  12. } else {
  13. while (isAlive()) {
  14. long delay = millis - now;
  15. if (delay <= 0) {
  16. break;
  17. }
  18. wait(delay);
  19. now = System.currentTimeMillis() - base;
  20. }
  21. }
  22. }

join等价于

  1. synichronized(thread.wait();){
  2. thread.wait();
  3. }

3.1 、CountDownLatch
3.2 、CyclicBarrier