Producer/Consumer threads using a Queue

前端 未结 7 1703
抹茶落季
抹茶落季 2020-11-22 17:00

I\'d like to create some sort of Producer/Consumer threading app. But I\'m not sure what the best way to implement a queue between the two.

So I\'ve so

7条回答
  •  伪装坚强ぢ
    2020-11-22 18:04

    I have extended cletus proposed answer to working code example.

    1. One ExecutorService (pes) accepts Producer tasks.
    2. One ExecutorService (ces) accepts Consumer tasks.
    3. Both Producer and Consumer shares BlockingQueue.
    4. Multiple Producer tasks generates different numbers.
    5. Any of Consumer tasks can consume number generated by Producer

    Code:

    import java.util.concurrent.*;
    
    public class ProducerConsumerWithES {
        public static void main(String args[]){
             BlockingQueue sharedQueue = new LinkedBlockingQueue();
    
             ExecutorService pes = Executors.newFixedThreadPool(2);
             ExecutorService ces = Executors.newFixedThreadPool(2);
    
             pes.submit(new Producer(sharedQueue,1));
             pes.submit(new Producer(sharedQueue,2));
             ces.submit(new Consumer(sharedQueue,1));
             ces.submit(new Consumer(sharedQueue,2));
             // shutdown should happen somewhere along with awaitTermination
             / * https://stackoverflow.com/questions/36644043/how-to-properly-shutdown-java-executorservice/36644320#36644320 */
             pes.shutdown();
             ces.shutdown();
        }
    }
    class Producer implements Runnable {
        private final BlockingQueue sharedQueue;
        private int threadNo;
        public Producer(BlockingQueue sharedQueue,int threadNo) {
            this.threadNo = threadNo;
            this.sharedQueue = sharedQueue;
        }
        @Override
        public void run() {
            for(int i=1; i<= 5; i++){
                try {
                    int number = i+(10*threadNo);
                    System.out.println("Produced:" + number + ":by thread:"+ threadNo);
                    sharedQueue.put(number);
                } catch (Exception err) {
                    err.printStackTrace();
                }
            }
        }
    }
    
    class Consumer implements Runnable{
        private final BlockingQueue sharedQueue;
        private int threadNo;
        public Consumer (BlockingQueue sharedQueue,int threadNo) {
            this.sharedQueue = sharedQueue;
            this.threadNo = threadNo;
        }
        @Override
        public void run() {
            while(true){
                try {
                    int num = sharedQueue.take();
                    System.out.println("Consumed: "+ num + ":by thread:"+threadNo);
                } catch (Exception err) {
                   err.printStackTrace();
                }
            }
        }   
    }
    

    output:

    Produced:11:by thread:1
    Produced:21:by thread:2
    Produced:22:by thread:2
    Consumed: 11:by thread:1
    Produced:12:by thread:1
    Consumed: 22:by thread:1
    Consumed: 21:by thread:2
    Produced:23:by thread:2
    Consumed: 12:by thread:1
    Produced:13:by thread:1
    Consumed: 23:by thread:2
    Produced:24:by thread:2
    Consumed: 13:by thread:1
    Produced:14:by thread:1
    Consumed: 24:by thread:2
    Produced:25:by thread:2
    Consumed: 14:by thread:1
    Produced:15:by thread:1
    Consumed: 25:by thread:2
    Consumed: 15:by thread:1
    

    Note. If you don't need multiple Producers and Consumers, keep single Producer and Consumer. I have added multiple Producers and Consumers to showcase capabilities of BlockingQueue among multiple Producers and Consumers.

提交回复
热议问题