Rohan Rohan - 12 days ago 5
Java Question

Unexpected output in Consumer Producer error

I got a code which I am trying to run it which is giving unexpcted output.

Code:

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ProducerConsumerBlockingQueue {

public static void main(String[] args) {
Buffer buffer = new Buffer();

ExecutorService executor = Executors.newFixedThreadPool(2);
executor.execute(new ProdBlock(buffer));
executor.execute(new ConsBlock(buffer));
executor.shutdown();
}

}
class ProdBlock implements Runnable{

Buffer buffer;
public ProdBlock(Buffer buffer) {
this.buffer = buffer;
}

public void run() {
for(int i = 1; i <= 10; i++){
buffer.put(i);
}

}

}
class ConsBlock implements Runnable{

Buffer buffer;
ConsBlock(Buffer buffer){
this.buffer = buffer;
}
public void run() {
for(int i = 1; i <= 10; i++){
buffer.get();
}
}

}
class Buffer{
int i;
BlockingQueue<Integer> sharedObject = new ArrayBlockingQueue<Integer>(1);

public void get(){
try {
System.out.println("Getting - " + sharedObject.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void put(int i){
this.i = i;
try {
sharedObject.put(i);
System.out.println("Putting - " + i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}


Output:

Putting - 1
Putting - 2
Getting - 1
Putting - 3
Getting - 2
Getting - 3
Putting - 4
Putting - 5
Getting - 4
Getting - 5
Putting - 6
Getting - 6
Putting - 7
Putting - 8
Getting - 7
Getting - 8
Putting - 9
Putting - 10
Getting - 9
Getting - 10


Expectd Output:

Putting - 1
Getting - 1
Putting - 2
Getting - 2
Putting - 3
Getting - 3
Putting - 4
Getting - 4
Putting - 5
Getting - 5
Putting - 6
Getting - 6
Putting - 7
Getting - 7
Putting - 8
Getting - 8
Putting - 9
Getting - 9
Putting - 10
Getting - 10


As expecting, blocking queue should take only 1 value at a time, how it is storing multiple values?

Answer

It's not storing multiple values. It's just that once the take() method has returned, the producer can add a value to the queue and print it before the other thread prints the taken value:

  1. producer thread: call put(1) - the queue has 1 element
  2. producer thread: print "Putting 1" - the queue has 1 element
  3. consumer thread: call take() - the queue is empty
  4. producer thread: call put(2) - the queue has 1 element
  5. producer thread: print "Putting 2" - the queue has 1 element
  6. consumer thread: concatenating the string "Getting - " with the integer 1 obtained at step 3, and printing the result - the queue has 1 element
Comments