Blocking queue and multi-threaded consumer, how to know when to stop

前端 未结 6 594
梦谈多话
梦谈多话 2020-12-04 06:53

I have a single thread producer which creates some task objects which are then added into an ArrayBlockingQueue (which is of fixed size).

I also start a

相关标签:
6条回答
  • 2020-12-04 07:33

    In your code-block where you attempt to retrive element from the queue , use poll(time,unit) instead of the take().

    try { 
        Object queueElement = inputQueue.poll(timeout,unit);
         //process queueElement        
     } catch (InterruptedException e) {
            if(!isRunning && queue.isEmpty())
             return ; 
     } 
    

    By specifying appropriate values of timeout , you ensure that threads wont keep blocking in case there is a unfortunate sequence of

    1. isRunning is true
    2. Queue becomes empty , so threads enter blocked wait ( if using take()
    3. isRunning is set to false
    0 讨论(0)
  • 2020-12-04 07:38

    Can not we do it using a CountDownLatch, where the size is the number of records in the producer. And every consumer will countDown after process a record. And its crosses the awaits() method when all tasks finished. Then stop all ur consumers. As all records are processed.

    0 讨论(0)
  • 2020-12-04 07:48

    There are a number of strategies you could use, but one simple one is to have a subclass of task that signals the end of the job. The producer doesn't send this signal directly. Instead, it enqueues an instance of this task subclass. When one of your consumers pulls off this task and executes it, that causes the signal to be sent.

    0 讨论(0)
  • 2020-12-04 07:52

    I'd send the workers a special work packet to signal that they should shut down:

    public class ConsumerWorker implements Runnable{
    
    private static final Produced DONE = new Produced();
    
    private BlockingQueue<Produced> inputQueue;
    
    public ConsumerWorker(BlockingQueue<Produced> inputQueue) {
        this.inputQueue = inputQueue;
    }
    
    @Override
    public void run() {
        for (;;) {
            try {
                Produced item = inputQueue.take();
                if (item == DONE) {
                    inputQueue.add(item); // keep in the queue so all workers stop
                    break;
                }
                // process `item`
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    

    }

    To stop the workers, simply add ConsumerWorker.DONE to the queue.

    0 讨论(0)
  • 2020-12-04 07:53

    You should continue to take() from the queue. You can use a poison pill to tell the worker to stop. For example:

    private final Object POISON_PILL = new Object();
    
    @Override
    public void run() {
        //worker loop keeps taking en element from the queue as long as the producer is still running or as 
        //long as the queue is not empty:
        while(isRunning) {
            System.out.println("Consumer "+Thread.currentThread().getName()+" START");
            try {
                Object queueElement = inputQueue.take();
                if(queueElement == POISON_PILL) {
                     inputQueue.add(POISON_PILL);//notify other threads to stop
                     return;
                }
                //process queueElement
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    
    //this is used to signal from the main thread that he producer has finished adding stuff to the queue
    public void finish() {
        //you can also clear here if you wanted
        isRunning = false;
        inputQueue.add(POISON_PILL);
    }
    
    0 讨论(0)
  • 2020-12-04 07:56

    I had to use a multi-threaded producer and a multi-threaded consumer. I ended up with a Scheduler -- N Producers -- M Consumers scheme, each two communicate via a queue (two queues total). The Scheduler fills the first queue with requests to produce data, and then fills it with N "poison pills". There is a counter of active producers (atomic int), and the last producer that receives the last poison pill sends M poison pills to the consumer queue.

    0 讨论(0)
提交回复
热议问题