Потребитель Java Producer - Почему не простой FixedThreadPool? - PullRequest
0 голосов
/ 19 июня 2019

Я немного читал о реализации потребительской реализации на Java. Большая часть онлайн-кода демонстрирует решение со следующим базовым объектом:

Очередь блокировки для использования в качестве канала данных

n номер источника, который отправил сообщения в очередь

n номер потребителя, который запрашивает данные из очереди

Обычно потребители отправляются в пул потоков, который завершает реализацию.

Другой вариант, который я исследовал, который практически не имел представления в Интернете, - это просто отправка задачи в качестве выполняемого объекта в FixedThreadPool.
В этой реализации бизнес-логика для обработки сообщения реализована в методе run() объекта Runnable. Когда у нас есть новое сообщение, которое мы хотим обработать, мы можем просто отправить новое задание такого типа на FixedThreadPool, и ... вот и все. Количество запущенных потоков управляется реализацией FixedThreadPool вместе с логикой опроса сообщений, и нам остается только реализовать логику бизнеса для нашего варианта использования.
Может кто-нибудь объяснить, почему это решение упускается из виду?
Есть ли какая-то конкретная причина, по которой нам нужно использовать очередь блокировки и опрос, когда язык Java уже реализовал это для нас?

public class ProducerConsumerExample{

    private ExecutorService pool;

    public ProducerConsumerExample(int numberOfThreads){
        this.pool = Executors.newFixedThreadPool(numberOfThreads);
    }

    public void submit(MessageObject msg){
        pool.submit(new MessagePrinter(msg));
    }

}

public class MessagePrinter implements  Runnable{
    private MessageObject msg;

    public MessagePrinter(MessageObject msg){
        this.msg = msg;
    }

    @Override
    public void run() {
        //only need to implement logic that is releavent for our use case
        System.out.println("Message recieved " + msg.toString());
    }
}

public static void main(String[] args){
    ProducerConsumerExample ex = new ProducerConsumerExample(5);
    for(int i=0;i<WHATEVER;i++){
        ex.submit(new MessageObject());
    }
}

Ответы [ 2 ]

0 голосов
/ 20 июня 2019

На самом деле, предпочтительно использовать пулы потоков в приложениях производителя-потребителя.Из Java Concurrency на практике:

Executor основан на шаблоне производитель-потребитель, где действия, которые представляют задачи, являются производителями (производящими единицы работы, которые должны быть выполнены) и потоками, которые выполняют задачиявляются потребителями (потребляющими эти единицы работы).Использование Executor, как правило, является самым простым способом реализации дизайна «производитель-потребитель» в вашем приложении.

При выборе реализации необходимо учитывать следующее:

  • Соединение: сколькоМожет ли производитель и потребитель знать друг о друге и о канале, соединяющем их вместе?
  • Внедрение базовой очереди: Какой тип Queue будет идеальным для работы?
  • Жизненный цикл: чтопроизойдет, если ThreadPool будет поврежден или остановлен?
  • Управление потоками и голодание: насколько вы вовлечены в управление вашими потоками?Долгоживущие против короткоживущих объектов?
0 голосов
/ 19 июня 2019

нет ничего плохого в вашем подходе, за исключением того, что не очевидно, какая очередь используется в пуле, созданном Executors.newFixedThreadPool(). Вы уверены, что не сможете получить RejectedExecutionException, если количество задач станет значительным?

Так что лучше используйте новое явное создание очереди задач с заранее заданным размером. Посмотрите на исходный код Executors.newFixedThreadPool(int).

...