线程的合并的含义就是 将几个并行线程的线程合并为一个单线程执行,应用场景是 当一个线程必须等待另一个线程执行完毕才能执行时,Thread类提供了join方法来完成这个功能,注意,它不是静态方法
    join有3个重载的方法:

    1. void join()
    2. 当前线程等该加入该线程后面,等待该线程终止。
    3. void join(long millis)
    4. 当前线程等待该线程终止的时间最长为 millis 毫秒。 如果在millis时间内,该线程没有执行完,那么当前线程进入就绪状态,重新等待cpu调度
    5. void join(long millis,int nanos)
    6. 等待该线程终止的时间最长为 millis 毫秒 + nanos 纳秒。如果在millis时间内,该线程没有执行完,那么当前线程进入就绪状态,重新等待cpu调度
    7. 复制代码

    例子代码,如下

    1. /**
    2. * 在主线程中调用thread.join(); 就是将主线程加入到thread子线程后面等待执行。不过有时间限制,为1毫秒。
    3. */
    4. public class Test1 {
    5. public static void main(String[] args) throws InterruptedException {
    6. MyThread t=new MyThread();
    7. t.start();
    8. // 将主线程加入到子线程后面,不过如果子线程在1毫秒时间内没执行完,
    9. // 则主线程便不再等待它执行完,进入就绪状态,等待cpu调度
    10. t.join(1);
    11. for(int i=0;i<30;i++){
    12. System.out.println(Thread.currentThread().getName() + "线程第" + i + "次执行!");
    13. }
    14. }
    15. }
    16. class MyThread extends Thread {
    17. @Override
    18. public void run() {
    19. for (int i = 0; i < 1000; i++) {
    20. System.out.println(this.getName() + "线程第" + i + "次执行!");
    21. }
    22. }
    23. }
    24. 复制代码

    在JDK中join方法的源码,如下:

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

    join方法实现是通过调用wait方法实现。当main线程调用t.join时候,main线程会获得线程对象t的锁(wait 意味着拿到该对象的锁),调用该对象的wait(等待时间),直到该对象唤醒main线程,比如退出后。这就意味着main 线程调用t.join时,必须能够拿到线程t对象的锁

    等多个线程采集数据之后再统计时间

    1. package com.huanghe.chapter5;
    2. /**
    3. * @author River
    4. * @date 2020/8/9 7:42
    5. * @description
    6. */
    7. public class ThreadJoin3 {
    8. public static void main(String[] args) throws InterruptedException {
    9. long startTime = System.currentTimeMillis();
    10. Thread t1 = new Thread(new CaptureRunnable("M1", 10000L));
    11. Thread t2 = new Thread(new CaptureRunnable("M2", 30000L));
    12. Thread t3 = new Thread(new CaptureRunnable("M4", 15000L));
    13. t1.start();
    14. t2.start();
    15. t3.start();
    16. // main 线程会等t1,t2,t3线程结束(t1,t2,t3的join是相对于当前线程,main线程的),t1,t2,t3会交替执行
    17. t1.join();
    18. t2.join();
    19. t3.join();
    20. long endTime = System.currentTimeMillis();
    21. System.out.printf("Save data begin timeStamp is : %s, end timestamp is:%s\n", startTime, endTime);
    22. }
    23. }
    24. class CaptureRunnable implements Runnable {
    25. private String machineName;
    26. private long spendTime;
    27. public CaptureRunnable(String machineName, Long spendTime) {
    28. this.machineName = machineName;
    29. this.spendTime = spendTime;
    30. }
    31. @Override
    32. public void run() {
    33. // do really something
    34. try {
    35. Thread.sleep(spendTime);
    36. System.out.println(machineName + " complete data capture");
    37. } catch (InterruptedException e) {
    38. e.printStackTrace();
    39. }
    40. }
    41. public String getResult() {
    42. return machineName + " finish";
    43. }
    44. }