实施生产者消费模式

时间:2011-10-24 11:23:18

标签: java multithreading concurrency producer-consumer executor

我正在尝试编写一个邮件实用程序,将邮件放在队列中,然后由消费者线程使用。

我正在尝试实现典型的生产者 - 消费者模式,但出现了问题。

我刚刚写了一个骨架,骨架没有按预期工作。

MailProducer.java

public class MailProducer implements Callable<Void>
 {

@Override
public Void call() throws Exception
{
    System.out.println("inside mail Producer");
    System.out.println("Thread executing = " +
                           Thread.currentThread().getName());
    return null;
}

}

MailConsumer.java

public class MailConsumer implements Callable<Void>
{

@Override
public Void call() throws Exception
{
    System.out.println("inside mail consumer");
    System.out.println("Thread executing = " + 
                        Thread.currentThread().getName());
    return null;
}

 }

最后是执行者

MailExecutor.java

  public class MailExecutor
  {

private static final int NTHREADS = 25;
private static final ExecutorService exec = 
                Executors.newFixedThreadPool(NTHREADS);

public static void main(String[] args)
{
    exec.submit(new MailConsumer());
    exec.submit(new MailProducer());

    System.out.println("inside main");

}

  }

现在,当我运行该程序时,我希望它能够让生产者和消费者来回继续打印各个类中的内容。但相反,程序在打印下面的行后会挂起/不执行任何操作。出了什么问题?我错过了什么吗?

输出 ...(输出不是我预期的。出了什么问题?)

   inside mail consumer
   inside main
   Thread executing = pool-1-thread-1
   inside mail Producer
   Thread executing = pool-1-thread-2

3 个答案:

答案 0 :(得分:2)

您缺少共享队列。没有队列,你什么都没有。

生产者将工作放入队列。消费者将工作排除在外。使用其BlockingQueueput()方法阻止电话的take()。在单独的线程中运行生产者和使用者允许他们在调用这些方法时安全地阻塞。

生产者和消费者都不需要Callable; Runnable会这样做。使用Executor将它们绑在一起是一个好主意。

答案 1 :(得分:1)

ExecutorService.submit为一次执行安排Runnable或Callable。您的输出显示MailProducer和MailConsumer都执行了一次,所以一切都按预期运行。

您应该将Producer和Consumer方法的内部放在循环中:

import java.util.concurrent.*;

public class Executor {

    private static final int NTHREADS = 25;
    private static final ExecutorService exec = 
        Executors.newFixedThreadPool(NTHREADS);


    public static void main(String[] args) {
        exec.submit(new MailConsumer());
        exec.submit(new MailProducer());

        System.out.println("inside main");  
    }


    static class MailProducer implements Runnable {
        @Override
        public void run() {
            while (true) {
                System.out.println("inside mail Producer");
                System.out.println("Thread executing = " +
                       Thread.currentThread().getName());
            }
       }
    }

    static class MailConsumer implements Runnable {
        @Override
        public void run() {
            while (true) {
                System.out.println("inside mail Consumer");
                System.out.println("Thread executing = " +
                       Thread.currentThread().getName());
            }
       }
    }
}

这给出了您期望的输出。

答案 2 :(得分:0)

  1. 您必须使用循环,以便多次执行生产者/消费者代码。

  2. 您的主题不会相互通信。目前,您只有两个线程正在执行。请查看BlockingQueue javadoc中的示例,了解如何执行此操作。