【问题标题】:ExecutorService doens't work执行器服务不起作用
【发布时间】:2016-03-12 06:34:50
【问题描述】:

我在使用 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和thread。

请帮帮我;( (我的英语不好,对不起)

【问题讨论】:

  • “不工作”是什么意思?你期望会发生什么,相反会发生什么?为什么调用queue.take() 会打印任何内容?
  • 对不起,我的英语不好。我的意思是如果我添加 queue.take() (不使用 System.out.println)这个过程永远不会停止。不是我修复了 queue.empty() 检查,while 循环中的第一行。
  • 不是 (x) 现在 (o) 我解决了这个问题。谢谢@JBNizet 我应该学会如何提问。

标签: java multithreading executorservice blockingqueue


【解决方案1】:

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

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

如果您的用例涉及首先由Producer 填充队列,然后运行Consumer 线程,您应该使用poll() 而不是take(),这样您可以检测到元素用完的情况。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-06-10
    • 2013-04-19
    • 1970-01-01
    • 2012-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多