是否保证Thread中的join()方法可以完美工作,或者还取决于各个JVM?

时间:2018-09-12 09:15:41

标签: java multithreading thread-safety

概述

我正在学习和使用Java中的线程。我刚刚开始研究join()方法。我了解它允许当前线程并强制其等待,直到thread.join()调用结束/停止/终止。

这是我尝试用来探索功能的代码:

ThreadJoinMain

package com.threeadjoin.main;

import sun.nio.ch.ThreadPool;

public class ThreadJoinMain {

public static void main(String[] args) {
    CustomThreadOne threadOne = new CustomThreadOne();

        Thread t1 = new Thread(threadOne);
        t1.setName("Thread 1");
        t1.setPriority(10);

        Thread t2 = new Thread(threadOne);
        t2.setName("Thread 2");

        /*Thread t3 = new Thread(threadOne);
        t3.setName("Thread 3");*/

        try{
            t1.join();
            //t2.join();
        }
        catch (InterruptedException e){
            e.printStackTrace();
        }

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

    }
}

CustomThreadOne

package com.threeadjoin.main;

public class CustomThreadOne implements Runnable{
    @Override
    public void run() {
        for(int i = 0; i < 10; i ++){
            System.out.println("Inside thread: " + 
Thread.currentThread().getName() + " value: " + i);
        }
    }
}

大多数情况下,这样的结果令人满意:

Inside thread: Thread 1 value: 0
Inside thread: Thread 1 value: 1
Inside thread: Thread 1 value: 2
Inside thread: Thread 1 value: 3
Inside thread: Thread 1 value: 4
Inside thread: Thread 1 value: 5
Inside thread: Thread 1 value: 6
Inside thread: Thread 1 value: 7
Inside thread: Thread 1 value: 8
Inside thread: Thread 1 value: 9
Inside thread: Thread 2 value: 0
Inside thread: Thread 2 value: 1
Inside thread: Thread 2 value: 2
Inside thread: Thread 2 value: 3
Inside thread: Thread 2 value: 4
Inside thread: Thread 2 value: 5
Inside thread: Thread 2 value: 6
Inside thread: Thread 2 value: 7
Inside thread: Thread 2 value: 8

但是,如果我连续运行此代码而不进行任何更改或强行重新构建它,则有时(尽管很少)输出如下:

Inside thread: Thread 1 value: 0
Inside thread: Thread 2 value: 0
Inside thread: Thread 1 value: 1
Inside thread: Thread 2 value: 1
Inside thread: Thread 1 value: 2
Inside thread: Thread 2 value: 2
Inside thread: Thread 1 value: 3
Inside thread: Thread 2 value: 3
Inside thread: Thread 1 value: 4
Inside thread: Thread 2 value: 4
Inside thread: Thread 1 value: 5
Inside thread: Thread 2 value: 5
Inside thread: Thread 1 value: 6
Inside thread: Thread 1 value: 7
Inside thread: Thread 1 value: 8
Inside thread: Thread 2 value: 6
Inside thread: Thread 1 value: 9
Inside thread: Thread 2 value: 7
Inside thread: Thread 2 value: 8
Inside thread: Thread 2 value: 9

或者这个:

Inside thread: Thread 2 value: 0
Inside thread: Thread 1 value: 0
Inside thread: Thread 2 value: 1
Inside thread: Thread 1 value: 1
Inside thread: Thread 2 value: 2
Inside thread: Thread 1 value: 2
Inside thread: Thread 2 value: 3
Inside thread: Thread 1 value: 3
Inside thread: Thread 2 value: 4
Inside thread: Thread 1 value: 4
Inside thread: Thread 2 value: 5
Inside thread: Thread 1 value: 5
Inside thread: Thread 2 value: 6
Inside thread: Thread 1 value: 6
Inside thread: Thread 2 value: 7
Inside thread: Thread 1 value: 7
Inside thread: Thread 2 value: 8
Inside thread: Thread 1 value: 8
Inside thread: Thread 2 value: 9
Inside thread: Thread 1 value: 9

这里有什么我想念的吗?

1 个答案:

答案 0 :(得分:1)

概述

好问题! 是的!它可以保证按预期工作,并且不依赖JVM 。但是,我在您的源代码中看到很多混淆点,因此我将使用类似的应用程序逐步介绍join()上的语义。让我们研究下面的示例。

示例应用

public static void main(String[] args) {
    // Create threads t1 -> t3
    Thread t1 = new Thread(threadOne);
    t1.setName("Thread 1");
    Thread t2 = new Thread(threadOne);
    t2.setName("Thread 2");
    Thread t3 = new Thread(threadOne);
    t3.setName("Thread 3");

    //////////// Explanation 1 /////////////

    t1.start(); // Begin execution of t1
    t2.start(); // Begin execution of t2

    //////////// Explanation 2 /////////////

     try {
         t1.join(); // Force main thread to wait for t1
    //////////// Explanation 3 /////////////
         t2.join(); // Force main thread to wait for t2
    //////////// Explanation 4 /////////////

         t3.start(); // Begin execution of t3
         t3.join(); // Force main thread to wait for t3
    //////////// Explanation 5 /////////////
     } catch (InterruptedException e) {
            e.printStackTrace();
     }
}

此处,此代码中实际上存在4个线程:maint1t2t3。主线程是应用程序创建并用于运行应用程序的起始线程。

说明1

这时,只有1个线程正在执行:main线程。尽管t1-> t3已创建,但尚未开始执行。

说明2

在这里,我们已经启动t1t2,以便有3个执行线程:t1t2main

说明3

t1.join()main线程(或 calling 线程)等待执行t1以完成操作。完成后,main线程将继续执行。此时,t2maint1并行执行。

说明4

main线程再次等待执行完成,但这一次是t2。完成后,main线程将被解除阻止并继续。

说明5

main线程已开始执行t3,并立即等待其完成。

摘要

总体而言,此示例应用程序产生不确定的结果。无法知道何时执行t1-> t3。具有不同结果是正常的,因为线程每次运行可能获得不同的CPU时间,从而导致它们在逻辑块中前进得更多或更少。我们所知道的是,main线程将确保t1t2在启动t3之前已经完成。同样,所有线程t1-> t3将在main线程完成之前完成执行。