我有 4 個執行緒。每個每 x 秒列印給定字母 x 次。任務是一次啟動 3 個執行緒,當至少一個先前的執行緒完成時,第 4 個執行緒。我不知道如何通知最后一個執行緒在適當的時候運行。
uj5u.com熱心網友回復:
CompletableFutures是以一種富有表現力的方式實作這一目標的現代方式。
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(3);
CompletableFuture<Void> a = CompletableFuture.runAsync(() -> print("A"), executor);
CompletableFuture<Void> b = CompletableFuture.runAsync(() -> print("B"), executor);
CompletableFuture<Void> c = CompletableFuture.runAsync(() -> print("C"), executor);
CompletableFuture.anyOf(a, b, c).thenRunAsync(() -> print("D"), executor);
}
private static void print(String taskName) {
for (int i = 0; i < 10_000; i) {
System.out.println("Task " taskName ": " i);
}
}
運行 A、B 和 C,然后當其中任何一個完成時,運行 D。
您可以通過洗掉執行程式并僅使用 fork/join 池來進一步簡化它,但它在獨立示例中效果不佳,因為它們是守護執行緒;該程式將在它做很多事情之前很快結束。
uj5u.com熱心網友回復:
要看你的任務是什么?你關心作業嗎?執行緒?
您總是可以通過使用三個執行緒創建執行緒池并給它四個任務來“破解它”:
ExecutorService es = Executors.newFixedThreadPool(3);
es.execute(() -> {
for (int i = 0; i < 10; i ) {
System.out.println("A");
try {Thread.sleep(100);} catch (InterruptedException e) {}
}
});
es.execute(() -> {
for (int i = 0; i < 10; i ) {
System.out.println("B");
try {Thread.sleep(100);} catch (InterruptedException e) {}
}
});
es.execute(() -> {
for (int i = 0; i < 10; i ) {
System.out.println("C");
try {Thread.sleep(100);} catch (InterruptedException e) {}
}
});
es.execute(() -> {
for (int i = 0; i < 10; i ) {
System.out.println("D");
try {Thread.sleep(100);} catch (InterruptedException e) {}
}
});
或者自己創建執行緒(首先是 D 執行緒),并在每個(ABC)的作業結束時詢問 D 是否正在運行,如果沒有,則啟動它。
有很多解決方案,其復雜性截然不同,它們是否可以完全取決于您的背景關系。
uj5u.com熱心網友回復:
要使用信號量等待 3 個執行緒之一完成,在啟動第 4 個不同執行緒之前,您可以將信號量初始化為0
. 在運行第 4 個執行緒之前,您獲取了信號量,但不能,因為它是0
. 當 3 個執行緒之一完成時,它會釋放信號量,允許第 4 個執行緒運行。
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Semaphore;
public class Main {
public static void main(String[] args) throws InterruptedException {
Semaphore sem = new Semaphore(0);
char[] letters = {'a', 'b', 'c'};
List<Thread> threadList = new ArrayList<>();
for (int threadNum = 0; threadNum < 3; threadNum ) {
int finalThreadNum = threadNum;
Thread t = new Thread(() -> {
for (int i = 0; i < 10; i ) {
System.out.print(letters[finalThreadNum]);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
sem.release();
});
threadList.add(t);
t.start();
}
Thread lastThread = new Thread(() -> {
for (int i = 0; i < 10; i ) {
System.out.print('d');
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
sem.acquire();
lastThread.start();
for (Thread t : threadList) {
t.join();
}
lastThread.join();
}
}
uj5u.com熱心網友回復:
您可以使用Semaphore
. 前 3 個執行緒將獲取所有許可,當第一個執行緒釋放許可時,第 4 個執行緒將獲取并運行。
public static void main(String [] args) throws IOException {
Semaphore semaphore = new Semaphore(3, true);
Runnable a = new Runnable() {
@Override
public void run() {
try {
semaphore.acquire();
for (int i = 0; i < 50; i ) {
System.out.println("A");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
semaphore.release();
}
}
};
Runnable b = new Runnable() {
@Override
public void run() {
try {
semaphore.acquire();
for (int i = 0; i < 50; i ) {
System.out.println("B");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
semaphore.release();
}
}
};
Runnable c = new Runnable() {
@Override
public void run() {
try {
semaphore.acquire();
for (int i = 0; i < 50; i ) {
System.out.println("C");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
semaphore.release();
}
}
};
Runnable d = new Runnable() {
@Override
public void run() {
try {
semaphore.acquire();
System.out.println("D");
} catch (Exception e) {
e.printStackTrace();
} finally {
semaphore.release();
}
}
};
ExecutorService exec = Executors.newFixedThreadPool(5);
exec.execute(a);
exec.execute(b);
exec.execute(c);
exec.execute(d);
}
uj5u.com熱心網友回復:
如果第 4 個執行緒的 semaphore.acquire() 發生在其他 3 個執行緒的獲取之前怎么辦...
你可以使用 a CountDownLatch
。基于@Ryan 的回答:
public static void main(String [] args) throws IOException {
Semaphore semaphore = new Semaphore(3, true);
CountDownLatch okToStartTaskD = new CountDownLatch(3);
Runnable a = new Runnable() {
@Override
public void run() {
try {
semaphore.acquire();
okToStartTaskD.countDown();
...
}
...
}
};
Runnable b = new Runnable() {
@Override
public void run() {
try {
semaphore.acquire();
okToStartTaskD.countDown();
...
}
...
}
};
...
ExecutorService exec = Executors.newFixedThreadPool(5);
exec.execute(a);
exec.execute(b);
exec.execute(c);
try {
okToStartTaskD.await();
}
catch (InterruptedException ex) {
ex.printStackTrace();
...should never get here, but what if?...
}
exec.execute(d);
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/470127.html