Java 线程中的join()方法是保证工作正常还是依赖于单个JVM?

Java 线程中的join()方法是保证工作正常还是依赖于单个JVM?,java,multithreading,thread-safety,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) { Cu

概述

我在学习和使用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();

    }
}
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();
     }
}
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

这里有我遗漏的东西吗

概述

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

示例应用程序

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();

    }
}
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个线程:
main
t1
t2
t3
。主线程是应用程序创建并用来运行应用程序的起始线程

解释1

此时,只有一个线程正在执行:
main
线程。虽然已经创建了
t1
->
t3
,但它们尚未开始执行

解释2

在这里,我们启动了
t1
t2
,因此有3个执行线程:
t1
t2
main

解释3

t1.join()。完成后,
main
线程继续执行。此时,
t2
main
t1
并行执行

解释4

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

解释5

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

摘要


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

您认为
thread.join()的作用是什么?因为你的代码显示你似乎不理解它的用法。具体地说,在线程启动之前加入它什么也不做:一个
join()
等待它被调用的线程停止,如果它还没有启动,它就不会等待。另外:如果您想要顺序行为,请不要使用其他线程。感谢您的回复。所以我把代码改成了这个。把这两行放在t1.start()上;t2.start();在试块之前,但仍然重复运行,得到不同的结果。我在哪里犯了错误,请让我知道。我重复一遍:如果你想要顺序行为,不要使用额外的线程。您似乎仍然不明白
join()
的作用。使用
t1.join()
只意味着当前线程将等待
t1
停止
t1
t2
仍将能够并行运行。如果您想要顺序行为,请不要使用其他线程-我肯定会将其作为建议,但不会解决我的查询。您似乎仍然不明白join()的作用我的第一行西亚斯,我正在学习。使用t1.join()只意味着当前线程将等待t1停止。t1和t2仍然能够并行运行--你确定???非常感谢。请编辑您的问题并描述您的想法
t1.join()
,这样我们就可以确切地知道您的误解在哪里,我们可以给您一个很好的解释。@AbhiroopNandiRay如果这个答案对您有帮助,请务必接受它作为帮助未来用户理解的答案!