006 线程中的join方法

一 . 概述

join方法的核心作用就是:

  当前线程等待子线程结束.

我们可以看到方法的重载,其实就是调用的线程等待子线程多少时间.

如果不传参数,默认为子线程完成之后才运行.


二 . 测试用例

public class JoinClass {
    
    public static void main(String[] args) {
        //创建一个线程,打印1到1000.
        Thread thread = new Thread() {
            @Override
            public void run() {
                print();
            }
        };
        //开启线程
        thread.start();
      // 加入子线程join ,那么主线程就会等待子线程完成任务.
      thread.join();
//主线程也做同样的操作 print(); } public static void print() { for(int i = 0 ; i<1000;i++) System.out.println(Thread.currentThread().getName() + " running .... i="+i); } }

现在我们创建了一个任务,打印1到1000,主线程和一个子线程分别进行.

打印的效果就是主线程和子线程不断切换运行状态.

当我们在原先的代码加入一行.

扫描二维码关注公众号,回复: 88630 查看本文章

看红色的部分,此时主线程就会等待子线程完成任务之后再去执行print()方法.


三 .分析

  一旦加入了红色部分的代码之后,那么主线程就会阻塞自己,直到子线程完成自己的任务之后才会被唤醒.

    因此,thread.join()方法一定要在print()方法之前,否则就不会在主线程开始任务就开始阻塞.

 [理解 ]:

  我们可以认为join()方法是一个将当前线程自我阻塞的方法,直到等待的线程完成之后才会运行.


 四 . 永无止尽的循环 

public class ForeverThread {
    
    public static void main(String[] args) throws Exception {
        // 主线程等待自己结束才会开始自己的任务...
        Thread.currentThread().join();
    }
}

上面的代码中,主线程一直在等待主线程自己运行结束.

  而主线程一直又在等待自己运行结束.

  那么就会出现一个循环.

        等待

    主线程--- ------> 主线程

        等待

如上,主线程自己就能将自己锁定,一直都无法结束掉.


五 . 一个例子 

  

public class TaskThread {
    public static void main(String[] args) throws Exception {
        long startTime = System.currentTimeMillis();
        Thread t1 = new Thread(new Task("task1",1));
        Thread t2 = new Thread(new Task("task2",2));
        Thread t3 = new Thread(new Task("task3",3));
        t1.start();
        t2.start();
        t3.start();
        t1.join();
        t2.join();
        t3.join();
        long endTime = System.currentTimeMillis();
        System.out.println("main thread is done,spned time is = " + (endTime - startTime));
    }
    
}

class Task implements Runnable{
    //任务的名字
    private final String taskName;
    //任务花费的时间
    private final long costTime;
    public Task(String taskName ,long costTime) {
        this.taskName = taskName ; 
        this.costTime = costTime;
    }
    
    public void run() {
        try {
            TimeUnit.SECONDS.sleep(costTime);
            System.out.println("任务 name = " + taskName + "完成了...");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    
}

我们创建了一个线程任务类,其中需要传入一个任务的名字,一个线程需要花费的时间.

在主线程之中,我们创建了三个线程,分别启动之后,使用join.现在运行的结果为: 

任务 name = task1完成了...
任务 name = task2完成了...
任务 name = task3完成了...
main thread is done,spned time is = 3002

  这个比较好理解: 主线程会在花费时间最长的线程结束之后终结自己.

下面我们调整一下代码的运行顺序:

  

    t1.start();
        t1.join();
        t2.start();
        t2.join();
        t3.start();
        t3.join();

现在是1线程首先运行,然后主线程等待1线程结束,然后再开启2线程,如此反复.

  那么,这个方法实际上就相当于一个序列化的运行方式进行着,就是在排队.

通过这个例子:

  我们知道join就是在阻塞自己,等待阻塞自己的任务结束之后才会运行自己.

猜你喜欢

转载自www.cnblogs.com/trekxu/p/8970459.html
006