Table of Contents
ToggleJava Thread join Method
讓目前正在執行的執行緒暫停,直到調用 join 的執行緒結束執行才會繼續執行任務,使用 join 方法,可以將不同執行緒結果整合在一起,與 wait 和 notify 方法一樣, Join Method in Java 是另一種執行緒間的同步機制,本篇增加了範例,並透過單元測試來驗證產出結果。
檔案目錄
./
+- src
+- test
| +- org
| +- ruoxue
| +- java_147
| +- multithreading
| +- thread
| +- ThreadJoinTest.java
單元測試
Thread join Java 提供執行緒等待、等待逾時等操作。
join
Thread join Java 建立執行緒 A 與執行緒 B ,每秒印出 1 個數字,執行緒 B 等待執行緒 A 執行結束,才會執行任務,印出數字。
@Test
public void join() {
Thread threadA = new Thread(() -> {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
String id = "A";
System.out.println(
sdf.format(new Date()) + " T[" + Thread.currentThread().getId() + "] worker: " + id + " ready");
IntStream.range(0, 3).forEach(e -> {
try {
System.out.println(sdf.format(new Date()) + " T[" + Thread.currentThread().getId() + "] " + e);
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
});
System.out.println(
sdf.format(new Date()) + " T[" + Thread.currentThread().getId() + "] worker: " + id + " finished");
});
Thread threadB = new Thread(() -> {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
String id = "B";
System.out.println(
sdf.format(new Date()) + " T[" + Thread.currentThread().getId() + "] worker: " + id + " ready");
try {
threadA.join();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
assertFalse(threadA.isAlive());
IntStream.range(0, 3).forEach(e -> {
try {
System.out.println(sdf.format(new Date()) + " T[" + Thread.currentThread().getId() + "] " + e);
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
});
System.out.println(
sdf.format(new Date()) + " T[" + Thread.currentThread().getId() + "] worker: " + id + " finished");
});
threadA.start();
threadB.start();
try {
assertTrue(threadA.isAlive());
threadB.join();
assertFalse(threadA.isAlive());
} catch (InterruptedException ex) {
ex.printStackTrace();
}
assertFalse(threadB.isAlive());
}
2023/02/10 13:42:32 T[11] worker: A ready
2023/02/10 13:42:32 T[12] worker: B ready
2023/02/10 13:42:32 T[11] 0
2023/02/10 13:42:33 T[11] 1
2023/02/10 13:42:34 T[11] 2
2023/02/10 13:42:35 T[11] worker: A finished
2023/02/10 13:42:35 T[12] 0
2023/02/10 13:42:36 T[12] 1
2023/02/10 13:42:37 T[12] 2
2023/02/10 13:42:38 T[12] worker: B finished
joinTimeout
Thread join Java 建立執行緒 A ,每秒印出 1 個數字,主執行緒等待 1 秒後逾時,繼續執行任務,然後結束,數字沒有全部印出。
@Test
public void joinTimeout() {
Thread threadA = new Thread(() -> {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
String id = "A";
System.out.println(
sdf.format(new Date()) + " T[" + Thread.currentThread().getId() + "] worker: " + id + " ready");
IntStream.range(0, 3).forEach(e -> {
try {
System.out.println(sdf.format(new Date()) + " T[" + Thread.currentThread().getId() + "] " + e);
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
});
System.out.println(
sdf.format(new Date()) + " T[" + Thread.currentThread().getId() + "] worker: " + id + " finished");
});
threadA.start();
try {
threadA.join(1000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
assertTrue(threadA.isAlive());
}
2023/02/10 13:43:55 T[11] worker: A ready
2023/02/10 13:43:55 T[11] 0
mainJoin
Thread join Java 建立執行緒 A 與執行緒 B ,每秒印出 1 個數字,執行緒 A 、 B 都執行結束後,主執行緒才會結束任務, Java join Thread 可以將不同執行緒結果整合在一起。
@Test
public void mainJoin() {
Thread threadA = new Thread(() -> {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
String id = "A";
System.out.println(
sdf.format(new Date()) + " T[" + Thread.currentThread().getId() + "] worker: " + id + " ready");
IntStream.range(0, 3).forEach(e -> {
try {
System.out.println(sdf.format(new Date()) + " T[" + Thread.currentThread().getId() + "] " + e);
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
});
System.out.println(
sdf.format(new Date()) + " T[" + Thread.currentThread().getId() + "] worker: " + id + " finished");
});
Thread threadB = new Thread(() -> {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
String id = "B";
System.out.println(
sdf.format(new Date()) + " T[" + Thread.currentThread().getId() + "] worker: " + id + " ready");
IntStream.range(0, 3).forEach(e -> {
try {
System.out.println(sdf.format(new Date()) + " T[" + Thread.currentThread().getId() + "] " + e);
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
});
System.out.println(
sdf.format(new Date()) + " T[" + Thread.currentThread().getId() + "] worker: " + id + " finished");
});
threadA.start();
threadB.start();
try {
threadA.join();
threadB.join();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
assertFalse(threadA.isAlive());
assertFalse(threadB.isAlive());
}
2023/02/10 13:46:29 T[12] worker: B ready
2023/02/10 13:46:29 T[11] worker: A ready
2023/02/10 13:46:29 T[11] 0
2023/02/10 13:46:29 T[12] 0
2023/02/10 13:46:30 T[11] 1
2023/02/10 13:46:31 T[12] 1
2023/02/10 13:46:31 T[11] 2
2023/02/10 13:46:32 T[11] worker: A finished
2023/02/10 13:46:33 T[12] 2
2023/02/10 13:46:35 T[12] worker: B finished
ThreadJoinTest.java
Java join Thread 新增單元測試,驗證 join Method in Java 是否符合預期。
package org.ruoxue.java_147.multithreading.thread;
import static org.junit.Assert.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;
import org.junit.Test;
public class ThreadJoinTest {
@Test
public void join() {
Thread threadA = new Thread(() -> {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
String id = "A";
System.out.println(
sdf.format(new Date()) + " T[" + Thread.currentThread().getId() + "] worker: " + id + " ready");
IntStream.range(0, 3).forEach(e -> {
try {
System.out.println(sdf.format(new Date()) + " T[" + Thread.currentThread().getId() + "] " + e);
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
});
System.out.println(
sdf.format(new Date()) + " T[" + Thread.currentThread().getId() + "] worker: " + id + " finished");
});
Thread threadB = new Thread(() -> {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
String id = "B";
System.out.println(
sdf.format(new Date()) + " T[" + Thread.currentThread().getId() + "] worker: " + id + " ready");
try {
threadA.join();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
assertFalse(threadA.isAlive());
IntStream.range(0, 3).forEach(e -> {
try {
System.out.println(sdf.format(new Date()) + " T[" + Thread.currentThread().getId() + "] " + e);
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
});
System.out.println(
sdf.format(new Date()) + " T[" + Thread.currentThread().getId() + "] worker: " + id + " finished");
});
threadA.start();
threadB.start();
try {
assertTrue(threadA.isAlive());
threadB.join();
assertFalse(threadA.isAlive());
} catch (InterruptedException ex) {
ex.printStackTrace();
}
assertFalse(threadB.isAlive());
}
@Test
public void joinTimeout() {
Thread threadA = new Thread(() -> {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
String id = "A";
System.out.println(
sdf.format(new Date()) + " T[" + Thread.currentThread().getId() + "] worker: " + id + " ready");
IntStream.range(0, 3).forEach(e -> {
try {
System.out.println(sdf.format(new Date()) + " T[" + Thread.currentThread().getId() + "] " + e);
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
});
System.out.println(
sdf.format(new Date()) + " T[" + Thread.currentThread().getId() + "] worker: " + id + " finished");
});
threadA.start();
try {
threadA.join(1000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
assertTrue(threadA.isAlive());
}
@Test
public void mainJoin() {
Thread threadA = new Thread(() -> {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
String id = "A";
System.out.println(
sdf.format(new Date()) + " T[" + Thread.currentThread().getId() + "] worker: " + id + " ready");
IntStream.range(0, 3).forEach(e -> {
try {
System.out.println(sdf.format(new Date()) + " T[" + Thread.currentThread().getId() + "] " + e);
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
});
System.out.println(
sdf.format(new Date()) + " T[" + Thread.currentThread().getId() + "] worker: " + id + " finished");
});
Thread threadB = new Thread(() -> {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
String id = "B";
System.out.println(
sdf.format(new Date()) + " T[" + Thread.currentThread().getId() + "] worker: " + id + " ready");
IntStream.range(0, 3).forEach(e -> {
try {
System.out.println(sdf.format(new Date()) + " T[" + Thread.currentThread().getId() + "] " + e);
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
});
System.out.println(
sdf.format(new Date()) + " T[" + Thread.currentThread().getId() + "] worker: " + id + " finished");
});
threadA.start();
threadB.start();
try {
threadA.join();
threadB.join();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
assertFalse(threadA.isAlive());
assertFalse(threadB.isAlive());
}
}
心得分享
Java Thread join with Examples 當在執行緒上調用 join 方法時,此執行緒會進入等待狀態,直到引用的執行緒結束任務,才會繼續執行工作,Java join Thread 取決於操作系統的定時,可以輸入 timeout 逾時時間來控制等候,join Method in Java 當等待時間到期時,此執行緒又會繼續執行任務。