【发布时间】:2014-01-26 04:27:56
【问题描述】:
我正在学习 java,我正在实现一个基本的生产者-消费者用例。 我有一个队列和一些将东西插入这个队列的生产者。 我还有一个实现 Callable 的消费者。下面是 Consumer 的实现:
public String call() throws Exception
{
while(true) {
if(!queue.isEmpty()) {
String prod = queue.poll();
System.out.println(name + " consumed " + prod);
}
}
}
制作人:
@Override
public void run() {
System.out.println("adding " + name);
queue.add(name);
}
主要:
public static void main(String[] args) {
Test();
}
public static void Test()
{
Queue<String> queue = new LinkedList<String>();
ScheduledExecutorService lots_of_producers = Executors.newScheduledThreadPool(10);
ExecutorService consumers = Executors.newFixedThreadPool(1);
for(int i=0; i<1; i++) {
Consumer consumer = new Consumer("consumer_" + i, queue);
consumers.submit(consumer);
}
for(int i=0; i<5; i++) {
Producer producer = new Producer("producer_" + i, queue);
lots_of_producers.scheduleWithFixedDelay(producer, i, 5, TimeUnit.SECONDS);
}
}
生产者工作正常,但消费者不工作,因为我没有看到消费者的日志。
但是,如果我更改消费实现并在 queue.isEmpty() 为 true 时让消费线程休眠,则消费按预期工作。
public String call() throws Exception
{
while(true) {
if(!queue.isEmpty()) {
String prod = queue.poll();
System.out.println(name + " consumed " + prod);
} else {
Thread.sleep(100);
}
}
}
谁能解释为什么消费者线程在第一种情况下不起作用?
对于第一种情况,在eclipse中我可以看到消费者线程没有死。我暂停它,它正在这条线上工作
if(!queue.isEmpty()) {
现在,如果我手动跨步,消费者将工作并打印日志。但是一旦我恢复并让它自己运行,它就会再次卡住。
我正在尝试更多地了解 java。
谢谢!
-尔本
【问题讨论】:
-
你应该使用某种
BlockingQueue。 -
您没有显示任何关于代码另一面的内容,但我怀疑您没有使用适当的线程安全队列实现。
-
也许您的消费者任务已终止(例如由于并发修改异常),如果发生这种情况,您不会看到任何异常,因为执行程序返回给您的未来会返回结果或异常,而不是产生嘈杂的崩溃。
-
手动创建线程同步既困难又容易出错!使用JDK本身提供的API。
-
哈哈。我找到了原因。 Java 链表不是线程安全的。我将调用包装在同步(队列)中,即使不使用 thread.sleep 也能正常工作。所以我学到了两件事: 1. java 很好地处理了线程。单个线程中的紧密循环不会影响其他线程。 2.linkedlist 不是线程安全的,竞争条件会导致未定义的行为(如挂起)。谢谢大家!
标签: java multithreading executorservice producer-consumer