Thread中的join()方法是否可以完美地工作,还是依赖于单个JVM?

问题描述 投票:0回答:1

概观

我正在学习和使用java中的Threads。我刚开始调查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

这里有什么我想念的吗?

java multithreading thread-safety
1个回答
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线程(或调用线程)等待t1的执行完成。完成后,main线程继续执行。在这一点上,t2maint1并行执行。

解释4

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

说明5

main线程已经开始执行t3s,并立即等待它完成。

摘要

总的来说,这个示例应用程序产生不确定的结果。无法知道何时会执行t1-> t3。具有不同的结果是正常的,因为线程可能每次运行获得不同的CPU时间,从而导致它们在其逻辑块中进一步或更远。我们所知道的是,main线程将确保t1t2在开始t3之前完成。此外,所有线程t1-> t3将在main线程完成之前完成执行。

© www.soinside.com 2019 - 2024. All rights reserved.