ExecutorService不起作用

时间:2016-03-12 06:34:51

标签: java multithreading executorservice blockingqueue

我使用Executorservice

时遇到问题

我实施了消费者 - 生产者模式

主要

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();


}
}

生产者

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);
        }
    }
}
}

消费

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;
        }
    }

}
}

我想知道为什么(Consumer.java)案例1不起作用, 但案例2很好

它打印注意并且永不停止(此评论不好。忽略它ㅠㅠ)

我只是想知道,为什么案例1不是停止。

System.out.println或BlockingQueue中有什么东西吗?

(Poducer.java也。如果我在Producer.java中添加print i然后抛出InterruptedException)

可能是我不熟悉java和线程。

请帮帮我;( (我的英语不好,抱歉)

1 个答案:

答案 0 :(得分:1)

这里的基本问题是,如果队列在queue.take()之前变为空,则消费者线程将阻塞,直到某些内容被添加到队列中。由于您在启动消费者之前完成了对队列的所有添加,因此,其中一个消费者是否会进入阻塞状态会很幸运。

似乎情况2(使用控制台输出)减慢了速度,没有线程进入此状态。在情况1处理如此之快以至于至少一个线程发现自己被阻塞。当我运行你的代码时,我发现线程3被阻塞,这意味着在线程3甚至有机会开始之前,线程1和2可能消耗了队列中的所有条目。

如果您的用例涉及首先由Producer填充队列,然后运行Consumer个帖子,则应使用poll()代替take(),这样您就可以检测到缺少元素的条件。