简体   繁体   中英

ExecutorService doens't work

I have problem using Executorservice

I implemented Consumer-Producer Pattern

Main

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

public class Main {

    public static void main(String[] args) {

    BlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(10000);

    Thread producer = new Thread(new Producer(queue));
    ExecutorService executorService = Executors.newFixedThreadPool(3);

    Runnable consumer1 = new Consumer(queue);
    Runnable consumer2 = new Consumer(queue);
    Runnable consumer3 = new Consumer(queue);

    producer.start();
    executorService.submit(consumer1);
    executorService.submit(consumer2);
    executorService.submit(consumer3);

    executorService.shutdown();


}
}

Producer

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

public class Producer implements Runnable{
public BlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(10000);

public Producer(BlockingQueue<Integer> queue) {
    this.queue = queue;
}

public synchronized void run() {

    for (int i=0; i<100; ++i) {
        try {
            //System.out.println("i = " + i);
            queue.put(i);
        } catch (InterruptedException e) {
            System.out.println(e);
        }
    }
}
}

Consumer

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

public class Consumer implements Runnable {

public BlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(10000);

public Consumer(BlockingQueue<Integer> queue) {
    this.queue = queue;
}

public void run() {
    while (true) {
        try {
            //queue.take(); // case 1
            System.out.println(Thread.currentThread().getName() + " Consumer : " + queue.take()); // case 2

        } catch (InterruptedException e) {
            System.out.println(e);
        }

        if (queue.isEmpty()) {
            break;
        }
    }

}
}

I wonder why (Consumer.java) case 1 is not working, but case 2 is fine

It print noting and never stopping (This comment isn't good. Ignore it ㅠㅠ)

I just wonder, Why case 1 is not Stop.

Is there something in System.out.println or BlockingQueue?

(Poducer.java also. If i added print i in Producer.java then Throws InterruptedException)

May be I don't know java and thread well.

Please help me ;( (My English isn't good, Sorry)

The fundamental problem here is that if the queue ever becomes empty just before the queue.take() , the consumer thread will block until something gets added to the queue. Since you do all the adding to the queue prior to starting the consumers, it is a matter of luck whether one of the consumers will get into a blocked state.

It appears that case 2 (with the console output) slows things down enough that no thread gets into this state. In case 1 processing is so fast that at least one thread finds itself blocked. When I ran your code I found thread 3 blocked, meaning that probably threads 1 and 2 consumed all entries in the queue before thread 3 even had a chance to get started.

If your usecase involves the queue being filled first by the Producer and then running the Consumer threads, you should use poll() instead of take() which will let you detect the condition of running out of elements.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM