簡體   English   中英

Java 生產者消費者停止消費者線程

[英]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編程的周到資料:

https://mkyong.com/java/java-blockingqueue-examples/

https://www.baeldung.com/java-blocking-queue

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM