这个线程连接代码是什么意思?

在这段代码中,两个连接和中断是什么意思? t1.join()导致 t2停止直到 t1终止?

Thread t1 = new Thread(new EventThread("e1"));
t1.start();
Thread t2 = new Thread(new EventThread("e2"));
t2.start();
while (true) {
try {
t1.join();
t2.join();
break;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
174907 次浏览

这个线程连接代码是什么意思?

引用 方法 javadocs的话:

等待线程死亡。

有一个线程正在运行您的示例代码,它可能是 主线

  1. 主线程创建并启动 t1t2线程。
  2. 主线程调用 t1.join()等待 t1线程完成。
  3. t1线程完成,t1.join()方法在主线程中返回。请注意,t1可能在 join()调用之前就已经完成了,在这种情况下,join()调用将立即返回。
  4. 主线程调用 t2.join()等待 t2线程完成。
  5. t2线程完成(或者它可能在 t1线程完成之前完成) ,t2.join()方法在主线程中返回。

重要的是要理解,t1t2线程一直在运行 并行,但是启动它们的主线程需要等到它们完成才能继续。这是常见的模式。而且,t1和/或 t2可能已经完成了 之前主线程对它们的 join()调用。如果是这样,那么 join()将不会等待,但会立即返回。

t1.join()表示导致 t2停止直到 t1终止?

没有。调用 t1.join()总台线程将停止运行并等待 t1线程完成。t2线程并行运行,完全不受 t1t1.join()调用的影响。

就 try/catch 而言,join()抛出 InterruptedException,这意味着调用 join()的主线程本身可能被另一个线程中断。

while (true) {

while循环中使用连接是一种奇怪的模式。通常,在每种情况下,先执行第一个联接,然后执行第二个联接,以适当地处理 InterruptedException。没必要让他们循环。

join()表示等待线程完成。这是一种阻断方法。您的主线程(执行 join()的线程)将在 t1.join()线上等待,直到 t1完成其工作,然后对 t2.join()执行相同的操作。

这是一个 最喜欢的 Java 面试问题。

Thread t1 = new Thread(new EventThread("e1"));
t1.start();
Thread e2 = new Thread(new EventThread("e2"));
t2.start();


while (true) {
try {
t1.join(); // 1
t2.join(); // 2  These lines (1,2) are in in public static void main
break;
}
}

t1.join()表示,t1表示类似于“ 我想第一个完成”的东西。t2的情况也是如此。无论是谁启动了 t1t2线程(在本例中是 main方法) ,main 都会等到 t1t2完成它们的任务。

然而,需要注意的一点是,t1t2本身 无论联接调用顺序如何,都可以并行运行t1t2。这是 main/daemon线程,必须 等等

来自 Oracle 文档 关于连接的页面

join方法允许一个线程等待另一个线程的完成。

如果 t1是当前正在执行线程的 Thread对象,

t1.join() : causes the current thread to pause execution until t1's thread terminates.

如果 t2是当前正在执行线程的 Thread对象,

t2.join(); causes the current thread to pause execution until t2's thread terminates.

join API 是低级 API,已经在 Java 的早期版本中引入。在并发性方面,很多东西在一段时间内都发生了变化(尤其是在 jdk 1.5发行版中)。

您可以使用 java.util.conserAPI 实现同样的功能

  1. ExecutorService上使用 调用所有
  2. 使用 CountDownLatch
  3. 使用 ExecutorsForkJoinPool偷窃工作池(从 java 8开始)

参考相关的社会工作者问题:

等待所有线程在 Java 中完成它们的工作

当线程 tA 调用 tB.join ()时,它的原因不仅是等待 tB 死亡或 tA 自身被中断,而且在 tB 中的最后一个语句和 tA 线程中 tB.join ()之后的下一个语句之间创建 Happen-before 关系。

线程中的所有操作都发生在其他线程从该线程的 join ()成功返回之前。

意思是程序

class App {
// shared, not synchronized variable = bad practice
static int sharedVar = 0;
public static void main(String[] args) throws Exception {
Thread threadB = new Thread(() -> {sharedVar = 1;});
threadB.start();
threadB.join();


while (true)
System.out.print(sharedVar);
}
}

一定要打印

>> 1111111111111111111111111 ...

但是程序

class App {
// shared, not synchronized variable = bad practice
static int sharedVar = 0;
public static void main(String[] args) throws Exception {
Thread threadB = new Thread(() -> {sharedVar = 1;});
threadB.start();
// threadB.join();  COMMENT JOIN


while (true)
System.out.print(sharedVar);
}
}

不仅可以打印

>> 0000000000 ... 000000111111111111111111111111 ...

但是

>> 00000000000000000000000000000000000000000000 ...

总是只有’0’。

因为 Java 内存模型不需要在没有 heppens-before 关系(线程启动、线程连接、使用‘ synchronized’关键字、使用 AtomicXXX 变量等)的情况下将‘ sharedVar’的新值从 threadB“转移”到主线程。

一幅画胜过千言万语。

    Main thread-->----->--->-->--block##########continue--->---->
\                 |               |
sub thread start()\                | join()        |
\               |               |
---sub thread----->--->--->--finish

希望对大家有用,详情请点击 给你

假设我们的主线程启动 t1和 t2线程。现在,当调用 t1.join ()时,主线程挂起自己,直到线程 t1死亡,然后恢复自己。 类似地,当 t2.join ()执行时,主线程再次挂起自己,直到线程 t2死亡,然后继续。

原来是这样的。

此外,这里并不真正需要 while 循环。

简而言之:
t1.join()在完成 t1之后返回。 < br/> 它不对 t1线程做任何事情,除了等待它完成。 < br/> 当然,代码遵循 t1.join()只会在 t1.join()返回。

对我来说,Join ()行为总是令人困惑,因为我试图记住谁将等待谁。 别这么想。

下面是纯等待()和通知()机制。

我们都知道,当我们对任何对象(t1)调用 wait ()时,调用对象(main)被发送到等待室(阻塞状态)。

在这里,主线程调用 join () ,而 join ()是 wait ()。因此,主线程将等待,直到收到通知。 T1在完成运行(线程完成)时给出通知。

收到通知后,main 从等候室出来并继续执行。

希望能有帮助!

package join;


public class ThreadJoinApp {


Thread th = new Thread("Thread 1") {
public void run() {
System.out.println("Current thread execution - " + Thread.currentThread().getName());
for (int i = 0; i < 10; i++) {
System.out.println("Current thread execution - " + Thread.currentThread().getName() + " at index - " + i);
}
}
};


Thread th2 = new Thread("Thread 2") {
public void run() {
System.out.println("Current thread execution - " + Thread.currentThread().getName());


//Thread 2 waits until the thread 1 successfully completes.
try {
th.join();
} catch( InterruptedException ex) {
System.out.println("Exception has been caught");
}


for (int i = 0; i < 10; i++) {
System.out.println("Current thread execution - " + Thread.currentThread().getName() + " at index - " + i);
}
}
};


public static void main(String[] args) {
ThreadJoinApp threadJoinApp = new ThreadJoinApp();
threadJoinApp.th.start();
threadJoinApp.th2.start();
}


//Happy coding -- Parthasarathy S
}

Join ()方法用于保持当前正在运行的线程的执行,直到指定的线程死亡(完成执行)。

为什么要使用 join ()方法?

在正常情况下,我们通常有多个线程,线程调度程序调度线程,这不能保证线程的执行顺序。

让我们看一个例子,创建一个新项目,然后复制下面的代码:

这是 activity _ main.xml 代码:

<?xml version="1.0" encoding="utf-8"?>


<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">


<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/btn_without_join"
app:layout_constraintTop_toTopOf="parent"
android:text="Start Threads Without Join"/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/btn_with_join"
app:layout_constraintTop_toBottomOf="@id/btn_without_join"
android:text="Start Threads With Join"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/tv"
app:layout_constraintTop_toBottomOf="@id/btn_with_join"
/>


</androidx.constraintlayout.widget.ConstraintLayout>

这是 MainActivity.java 的代码:

public class MainActivity extends AppCompatActivity {


TextView tv;
volatile  String threadName = "";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = findViewById(R.id.tv);
Button btn_without_join = findViewById(R.id.btn_without_join);
btn_without_join.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
withoutJoin();
}
});
Button btn_with_join = findViewById(R.id.btn_with_join);
btn_with_join.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
withJoin();
}
});
}
private void withoutJoin()
{
tv.setText("");
Thread th1 = new Thread(new MyClass2(), "th1");
Thread th2 = new Thread(new MyClass2(), "th2");
Thread th3 = new Thread(new MyClass2(), "th3");
th1.start();
th2.start();
th3.start();
}
private void withJoin()
{
tv.setText("");
Thread th1 = new Thread(new MyClass2(), "th1");
Thread th2 = new Thread(new MyClass2(), "th2");
Thread th3 = new Thread(new MyClass2(), "th3");
th1.start();
try {
th1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
th2.start();
try {
th2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
th3.start();
}
class MyClass2 implements Runnable{


@Override
public void run() {
Thread t = Thread.currentThread();
runOnUiThread(new Runnable() {
public void run() {
tv.setText(tv.getText().toString()+"\n"+"Thread started: "+t.getName());
}
});
try {
Thread.sleep(1000);
} catch (InterruptedException ie) {
ie.printStackTrace();
}
runOnUiThread(new Runnable() {
public void run() {
tv.setText(tv.getText().toString()+"\n"+"Thread ended: "+t.getName());
}
});


}
}
}

如果您按下第一个按钮(启动线程而不加入) ,这将是结果: enter image description here

如果你按下第二个按钮(启动加入线程) ,结果就是这样: enter image description here