Я хотел бы использовать очереди и рабочие потоки демона, которые всегда работают, и ждать, пока что-то поступит в очередь.Таким образом, гарантируется, что только один работник работает по запросу.Если вы хотите, чтобы запускался только один поток, уменьшите POOLSIZE до 1 или используйте newSingleThreadExecutor.
Я не совсем понимаю ваше второе требование: вы имеете в виду, что только 1 поток может быть запущен в качестве фоновой задачи?Если это так, вы можете создать еще один SingleThreadExecutor и использовать его для фоновой задачи.Тогда не имеет большого смысла иметь значение POOLSIZE> 1, если только работа, выполняемая в фоновом потоке, не очень коротка по сравнению с работой, выполняемой в самом работнике.
private static interface Request {};
private final int POOLSIZE = 10;
private final int QUEUESIZE = 1000;
BlockingQueue<Request> e = new LinkedBlockingQueue<Request>(QUEUESIZE);
public void startWorkers() {
ExecutorService threadPool = Executors.newFixedThreadPool(POOLSIZE);
for(int i=0; i<POOLSIZE; i++) {
threadPool.execute(new Runnable() {
@Override
public void run() {
try {
final Request request = e.take();
doStuffWithRequest(request);
} catch (InterruptedException e) {
// LOG
// Shutdown worker thread.
}
}
});
}
}
public void handleRequest(Request request) {
if(!e.offer(request)) {
//Cancel request, queue is full;
}
}
Во время запуска начинающие рабочие запускаютсярабочие (сюрприз!).handleRequest обрабатывает запросы, поступающие от веб-службы, сервлета или чего-либо еще.
Конечно, вам нужно адаптировать «Request» и «doStuffWithRequest» к вашим потребностям, добавить дополнительную логику для выключения и т. д.