概述
我正在学习和使用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
这里有什么我想念的吗?
答案 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个线程:main
,t1
,t2
,t3
。主线程是应用程序创建并用于运行应用程序的起始线程。
说明1
这时,只有1个线程正在执行:main
线程。尽管t1
-> t3
已创建,但尚未开始执行。
说明2
在这里,我们已经启动t1
和t2
,以便有3个执行线程:t1
,t2
和main
。
说明3
在t1.join()
,main
线程(或 calling 线程)等待执行t1
以完成操作。完成后,main
线程将继续执行。此时,t2
与main
和t1
并行执行。
说明4
main
线程再次等待执行完成,但这一次是t2
。完成后,main
线程将被解除阻止并继续。
说明5
main
线程已开始执行t3
,并立即等待其完成。
摘要
总体而言,此示例应用程序产生不确定的结果。无法知道何时执行t1
-> t3
。具有不同结果是正常的,因为线程每次运行可能获得不同的CPU时间,从而导致它们在逻辑块中前进得更多或更少。我们所知道的是,main
线程将确保t1
和t2
在启动t3
之前已经完成。同样,所有线程t1
-> t3
将在main
线程完成之前完成执行。