Изящно реализующие индикаторы длины очереди к ExecutorServices

Да ведь о, почему не делает java.util.concurrent предоставьте длине очереди индикаторы для ExecutorServices? Недавно я делал что-то вроде этого:

ExecutorService queue = Executors.newSingleThreadExecutor();
AtomicInteger queueLength = new AtomicInteger();
...

public void addTaskToQueue(Runnable runnable) {
    if (queueLength.get() < MAX_QUEUE_LENGTH) {
        queueLength.incrementAndGet(); // Increment queue when submitting task.
        queue.submit(new Runnable() {
            public void run() {
                runnable.run();
                queueLength.decrementAndGet(); // Decrement queue when task done.
            }
        });
    } else {
        // Trigger error: too long queue
    }
}

Который работает хорошо, но... Я думаю, что это действительно должно быть реализовано как часть ExecutorService. Это является немым и подверженным ошибкам для переноса вокруг счетчика, разделенного от фактической очереди, на длину которой счетчик, как предполагается, указывает (напоминает мне о массивах C). Но, ExecutorServices получены через статические методы фабрики, таким образом, нет никакого способа просто расширить в других отношениях превосходного единственного исполнителя потока и добавить счетчик очереди. Таким образом, что должно я делать:

  1. Переосмыслить материал, уже реализованный в JDK?
  2. Другое умное решение?
33
задан Joonas Pulakka 15 February 2010 в 17:36
поделиться

1 ответ

Есть более прямой путь:

ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newSingleThreadExecutor();
// add jobs
// ...
int size = executor.getQueue().size();

Хотя вы можете рассмотреть возможность не использовать удобные методы create в Executor, а создать исполнитель напрямую, чтобы избавиться от приведения и быть уверенным, что исполнитель всегда будет ThreadPoolExecutor, даже если реализация Executors.newSingleThreadExecutor когда-нибудь изменится.

ThreadPoolExecutor executor = new ThreadPoolExecutor( 1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>() );

Это напрямую скопировано из Executors.newSingleThreadExecutor в JDK 1.6. LinkedBlockingQueue, который передается конструктору, на самом деле является тем самым объектом, который вы получите обратно от getQueue.

57
ответ дан 27 November 2019 в 18:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: