How to stop the producer thread if consumer thread faces an exception

Ayush :

i have this producer consumer situation where i am using arrayblockingqueue. How to stop producer thread if consumer thread faces exception. i need producer to stop waiting for queue to be empty . i have induced a forced runtime exception . But the program does not exits . Producers keep waiting fr the queue to be empty . can someone please help

public class ServiceClass implements Runnable{

    private final static BlockingQueue<Integer> processQueue = new ArrayBlockingQueue<>(10);
    private static final int CONSUMER_COUNT = 1;
    private boolean isConsumerInterrupted = false;

    private boolean isConsumer = false;
    private static boolean producerIsDone = false;

    public ServiceClass(boolean consumer,boolean isConsumerInterrupted) {
        this.isConsumer = consumer;
        this.isConsumerInterrupted = isConsumerInterrupted;
    }

    public static void main(String[] args) {

        long startTime = System.nanoTime();

        ExecutorService producerPool = Executors.newFixedThreadPool(1);
        producerPool.submit(new ServiceClass(false,false)); // run method is
                                                         // called   
        // create a pool of consumer threads to parse the lines read
        ExecutorService consumerPool = Executors.newFixedThreadPool(CONSUMER_COUNT);
        for (int i = 0; i < CONSUMER_COUNT; i++) {
            consumerPool.submit(new ServiceClass(true,false)); // run method is
                                                            // called
        }
        producerPool.shutdown();
        consumerPool.shutdown();

        while (!producerPool.isTerminated() && !consumerPool.isTerminated()) {
        }

        long endTime = System.nanoTime();
        long elapsedTimeInMillis = TimeUnit.MILLISECONDS.convert((endTime - startTime), TimeUnit.NANOSECONDS);
        System.out.println("Total elapsed time: " + elapsedTimeInMillis + " ms");

    }



    @Override
    public void run() {
        if (isConsumer) {
            consume();
        } else {
            readFile(); //produce data by reading a file
        }
    }

    private void readFile() {
        //Path file = Paths.get("c:/temp/my-large-file.csv");
        try
        {

            for(int i =0;i<10000;i++) {
                if(isConsumerInterrupted) {
                    break;
                }
                processQueue.put(i);
                System.out.println("produced:" + i+"------"+processQueue.size());

            }
            //Java 8: Stream class


        } catch (Exception e){
            e.printStackTrace();
        }

        producerIsDone = true; // signal consumer
        System.out.println(Thread.currentThread().getName() + " producer is done");
    }

    private void consume() {
        try {
            while (!producerIsDone || (producerIsDone && !processQueue.isEmpty())) {

                System.out.println("consumed:" + processQueue.take()+"------"+processQueue.size());
                throw new RuntimeException();

                //System.out.println(Thread.currentThread().getName() + ":: consumer count:" + linesReadQueue.size());                
            }
            System.out.println(Thread.currentThread().getName() + " consumer is done");
        } catch (Exception e) {
            isConsumerInterrupted=true;
        }


    }




}
Ravindra Ranwala :

You are using a flag isConsumerInterrupted to terminate the Producer thread. This is wrong. The consumer does not consume elements from the queue, and Producer keeps producing until the queue is full and then starts blocking until the queue becomes nonfull. Then when the consumer throws a RuntimeException it sets the flag, and the Producer thread gets no chance to check the flag, since none of the consumers consume the elements from the queue so that the Producer can emerge from the waiting state. One option is to use a future and cancel it when consumer throws an exception contrary to setting the flag. Since the processQueue.put is responsive to the interruption, it will terminate the producer thread successfully. An InterruptedException is thrown- if interrupted while waiting. Here's how it looks.

private static Future<?> producerFuture = null;
public static void main(String[] args) {

    // Remainder omitted.
    producerFuture = producerPool.submit(new ServiceClass(false, false)); 
    // ...
}

private void consume() {
    try {
        // ...
    } catch (Exception e) {
        producerFuture.cancel(true);
    }
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326557&siteId=1