Реализация шаблона потребителя Producer - PullRequest
3 голосов
/ 24 октября 2011

Я пытаюсь написать почтовую утилиту, которая помещает почту в очередь, и позже она используется потоком потребителя.

Я пытаюсь реализовать типичный шаблон производитель-потребитель, но что-то идет не так.

Я только что написал скелет, и он работает не так, как ожидалось.

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 ]

2 голосов
/ 24 октября 2011

Вам не хватает общей очереди. Без очереди у вас ничего нет.

Производители ставят работу в очередь. Потребители снимают работу с очереди. Используйте BlockingQueue, чьи put() и take() методы являются блокирующими вызовами. Запуск производителей и потребителей в отдельных потоках позволяет им безопасно блокировать при вызове этих методов.

Ни производители, ни потребители не должны быть Callable; Runnable сделает. Хорошая идея - использовать Executor, чтобы связать все это вместе.

1 голос
/ 24 октября 2011

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

Это даетожидаемый результат.

0 голосов
/ 24 октября 2011
  1. Вы должны использовать циклы, чтобы ваш код производителя / потребителя выполнялся более одного раза.

  2. Ваши потоки не взаимодействуют друг с другом.В настоящее время у вас есть только два выполняемых потока.Посмотрите на пример в BlockingQueue о том, как это сделать.

...