Да ведь о, почему не делает java.util.concurrent
предоставьте длине очереди индикаторы для ExecutorService
s? Недавно я делал что-то вроде этого:
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). Но, ExecutorService
s получены через статические методы фабрики, таким образом, нет никакого способа просто расширить в других отношениях превосходного единственного исполнителя потока и добавить счетчик очереди. Таким образом, что должно я делать:
Есть более прямой путь:
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
.