[英]Java producer consumer stop consumer threads
我有這段代碼,我想要一個停止消費者線程的好方法:
import java.util.ArrayDeque;
import java.util.Queue;
import java.util.concurrent.atomic.AtomicBoolean;
public class Foo {
private final Queue<Object> queue;
private final AtomicBoolean doneReading;
private final int numberOfThreads = 4, N = 100;
public Foo() {
queue = new ArrayDeque<>();
doneReading = new AtomicBoolean(false);
}
public void execute() throws InterruptedException {
Thread[] threads = new Thread[numberOfThreads];
for (int i = 0; i < numberOfThreads; i++) {
threads[i] = new Thread(() -> {
try {
synchronized (queue) {
while (!doneReading.get() || !queue.isEmpty()) {
if (queue.isEmpty()) {
queue.wait();
if (!queue.isEmpty()) {
Object element = queue.remove();
// Do stuff
}
}
else {
Object element = queue.remove();
// Do stuff
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
});
threads[i].start();
}
for (int i = 0; i < N; i++) {
synchronized (queue) {
queue.add(new Object());
queue.notifyAll();
}
}
doneReading.set(true);
synchronized (queue) {
queue.notifyAll();
}
for (Thread thread : threads) {
thread.join();
}
}
}
基本上,當我讀取了所有需要處理的數據后,我希望消費者線程停止。 我試過 while(.doneReading.get()) 但這並不能保證隊列中沒有任何剩余的項目。 我補充說,queue.isEmpty()。 但在這種情況下,一些線程會繼續等待,即使它們不會收到任何通知。 所以我設法再次調用 notifyAll(),這似乎確實有效,我還想過在隊列中添加一個 null。 並且每當消費者讀取 null 時,它會退出嗎? 哪種方法更好,或者有沒有更好的想法?
一種常用的方法是“毒丸”。 在隊列中放置一個特殊值,當讀取時會殺死消費者線程。 這使他們能夠處理所有值,並且在讀取超過最終值並讀取毒丸之前不會停止。
更多信息: https://java-design-patterns.com/patterns/poison-pill/
我也喜歡這些網站,他們經常有關於Java編程的周到資料:
class LimitedQueue<T> {
ArrayDeque<T> queue = new ArrayDeque<>();
boolean done = false;
synchronized void add (T item) {
queue.add(item);
notifyAll();
}
synchronized void done()
done=true;
notifyAll();
}
// most complex method
// waits until next item or done signal is put
synchronized boolean isDone() {
for (;;) {
if (!queue.isEmpty(){
return false;
}
if (done) {
return true;
}
wait();
}
}
syncronized T remove() {
return deque.remove();
}
}
LimitedQueue<Object> queue = new LimitedQueue<>();
class ConsumerThread extends Thread {
public void run(){
while (!queue.isDone()) {
Object element = queue.remove();
// do stuff
}
}
}
class ProducerThread extends Thread {
public void run() {
for (int i = 0; i < N; i++) ,{
queue.add(new Object());
}
queue.done();
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.