0

I am doing some exercise with multithreading and Java concurrency features. I have 1 producer and 4 consumers. Now my questions is: Is there any other more smart way to stop the consumers when I am sure that the producer have finished to produce in the BlockingQueue? For now I am using a -1 Integer in the queue but look very rudimentary way!! Thank you

public class Exercise {

static class Producer implements Runnable {
    int counter=0;
    private BlockingQueue<Integer> queue;
    Producer(BlockingQueue<Integer> q) { 
        queue = q;
    }
    public void run() {
        try {
            while (counter<100000000) {
                queue.put(produce());
            }
            queue.put(new Integer(-1));
            queue.put(new Integer(-1));
            queue.put(new Integer(-1));
            queue.put(new Integer(-1));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    Integer produce() {
        counter++;
        return new Integer(counter);

    }
}

static class Consumer implements Runnable {
    private final BlockingQueue<Integer> queue;
    private String name;
    private long sum;

    Consumer(BlockingQueue<Integer> q, String name) { 
        queue = q; 
        this.name=name;
        sum=0;
    }

    public void run() {
        try {
            int x=0;
            while (x>=0) {
                x=queue.take();
                if(x!=-1)sum+=x;
            }
            System.out.println(sum+" of "+ name);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}



public static void main(String[] args) {

    ExecutorService exec = Executors.newFixedThreadPool(6);
    BlockingQueue<Integer> q =new LinkedTransferQueue<Integer>();
    Producer p=new Producer(q);    
    Consumer c1 = new Consumer(q,"consumer1");
    Consumer c2 = new Consumer(q,"consumer2");
    Consumer c3 = new Consumer(q,"consumer3");
    Consumer c4 = new Consumer(q,"consumer4");
    exec.submit(p);
    exec.submit(c1);
    exec.execute(c2);
    exec.submit(c3);
    exec.execute(c4);
    exec.shutdown();
}

}

Andrea
  • 1

1 Answers1

1

You can use a poison pill, however a more robust way to use such a poison pill is to not remove it from the queue (or to put it back if you do) This way to producer doesn't need to know how many consumers you have.

BTW I would avoid using explicit boxing as it is more verbose and slower.

Instead of

queue.put(new Integer(-1));

you can write

queue.put(-1);

or even better

static final int POISON_PILL = -1;

// on the producer
queue.put(POISON_PILL);

// on the consumer
while ((x = queue.take()) != POISON_PILL) {
    sum += x;
queue.put(POISON_PILL);
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130