我正在学习Java,并且正在实现基本的生产者消费者用户酶。我有一个队列,一些生产商正在将东西插入此队列。我也有一个消费者可召唤。这是消费者的实施:
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()为真时让消费者线程睡眠,则消费者按预期工作。
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。
谢谢!
-erben
在这种情况下有多个问题。
- 您的第一个实现将运行一个紧密的循环。根据平台和螺纹模型,它可能根本不允许任何其他线程运行。这就是为什么生产者线程没有机会将数据放入队列的原因。
- 您的第二个实现(带有
Thread.sleep
)为其他线程运行提供了机会。这就是为什么您会看到消费者消耗某些东西的原因,因为生产者线程有机会将数据放在队列中。但是,即使您尚未同步生产商和消费者,即使是该失败也开放。参见Java教程 - 学习线程同步的同步。