Шаблон производитель / потребитель в Java - PullRequest
2 голосов
/ 15 августа 2011

Я думаю, как реализовать шаблон «производитель / потребитель» в Java.

Предположим, что у меня есть 3 потока и список, содержащий задачи (скажем, это около 5 задач). Каждый поток захватывает задачу из списка и выполняет ее одновременно. Мой текущий подход заключается в использовании CountDownLatch

int N = 3;
CountDownLatch startSignal = new CountDownLatch(1);
CountDownLatch doneSignal = new CountDownLatch(N);
ConcurrentLinkedQueue<String> tasks = new ConcurrentLinkedQueue<String>();

main() {
    for (int i=0;i<N;i++) {
        new Thread(new Worker()).start();
    }
    startSignal.countDown();
    doneSignal.await();
    System.out.println("done");
}

class Worker implements Runnable {
    public void run() {
        startSignal.await();
            while ((s = tasks.poll()) != null) {
                // do lengthy task here
                if (task failed) {
                    tasks.add(s);
                    return; // assume that task fails badly and have to stop the thread
                }
            }
        doneSignal.countDown();
    }
}

я хотел добиться того, чтобы при обработке задачи произошел сбой потока, он будет добавлен обратно в список задач для повторного выбора текущим или любым другим потоком, но при моем текущем подходе с использованием CountDownLatch, очевидно, это сделать это невозможно, поскольку после вызова doneSignal.countDown () поток предполагает, что он уже завершил задачу.

Каков наилучший подход для этого сценария? Является ли использование Executor единственным способом?

1 Ответ

3 голосов
/ 15 августа 2011

Я бы сказал, что это слишком сложное (и подверженное ошибкам) ​​решение для этого случая, было бы действительно проще использовать общий BlockingQueue, одиночный поток, опрашивающий из этой очереди блокировки и передававший задания в ExecutorService.

Не вижу причин, по которым вам понадобится CountDownLatch в этом случае, он просто излишне усложняет вашего работника, который должен понимать, что он работает в многопоточной среде, а также должен очищать все, что загрязненокогда это закончится.BlockingQueues и ExecutorServices созданы для того, чтобы помочь вам справиться с этими проблемами.

...