实现生产者消费者模式

发布于 2024-12-11 08:02:36 字数 1569 浏览 0 评论 0原文

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

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

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

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

I am trying to write a mail utility that places mails in a queue, and it is later consumed by a consumer thread.

I am trying to implement a typical producer-consumer pattern, but something is going wrong.

I just wrote a skeleton , and the skeleton is not working as expected.

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

 }

and finally the Executor

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

}

  }

Now when I run the program, I expect it to go back and forth the producer and consumer to keep printing what is written in the respective classes. But instead , the program hangs/does nothing after printing the below lines . What is going wrong ? Am I missing something?

Output ...(Output is not what I had expected. What is going wrong ?)

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

成熟的代价 2024-12-18 08:02:36

您缺少共享队列。没有队列,你就一无所有。

生产者将工作放入队列中。消费者将工作从队列中移除。使用 BlockingQueue< /a>,其 put()take() 方法是阻塞调用。在单独的线程中运行生产者和消费者允许他们在调用这些方法时安全地阻塞。

生产者和消费者都不需要 可调用Runnable 就可以了。使用 执行器< /a> 将它们结合在一起是个好主意。

You are missing the shared queue. Without the queue, you have nothing.

Producers put work onto the queue. Consumers take work off the queue. Use a BlockingQueue, whose put() and take() methods are blocking calls. Running producers and consumers in separate threads allows them to safely block while calling these methods.

Neither the producers nor the consumers need to be Callable; Runnable will do. Using an Executor to tie it all together is a good idea.

甚是思念 2024-12-18 08:02:36

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

这会给出您期望的输出。

ExecutorService.submit schedules a Runnable or Callable for one execution. Your output shows that MailProducer and MailConsumer both executed once, so everything works like it should.

You should place the inside of your Producer and Consumer methods in loops:

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

This gives the output you expect.

枯寂 2024-12-18 08:02:36
  1. 您必须使用循环,以便您的生产者/消费者代码执行多次。

  2. 您的线程之间不进行通信。目前您只有两个线程正在执行。查看 BlockingQueue 中的示例 如何执行此操作的 javadoc。

  1. You must use loops so that your producer/consumer code is executed more than once.

  2. Your threads do not communicate with each other. Currently you have only two threads being executed. Look at the example in the BlockingQueue javadoc of how to do it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文