Я согласен с @d Леванта, Блокировка очереди является ключом для использования здесь. С блокировкой очереди вам не нужно обрабатывать сценарий с пустой или пустой очередью.
В классе задач,
while(true) {
// Let queue be a synchronized, global queue
if (queue has an element) {
// Pop from queue and do a very minimal amount of work on it
// Involves a small amount of network IO (maybe 10-100 ms)
} else {
sleep(2000);
}
}
Его действительно не хороший подход, его неэффективным, потому что ваш цикл в то время непрерывно опроса, даже вы поставили нить сна(), но до сих пор его также накладные расходы ненужные контекстные переключатели каждый раз, когда поток пробуждается и спит.
На мой взгляд, ваш подход к использованию Исполнителей выглядит хорошо для вашего дела. Создание потоков, очевидно, является дорогостоящим процессом, а исполнители предоставляют нам гибкость повторного использования одного и того же потока для разных задач. Вы можете просто передать свое задание через execute(Runnable)
или submit(Runnable/Callable)
, а затем остальное позаботится об исполнителях внутри страны. Исполнители внутренне используют только концепцию блокировки очереди.
Вы даже можете создать свой собственный пул потоков, используя класс ThreadPoolExecutor и передав требуемый параметр в его конструкторе, здесь вы можете передать свою собственную блокирующую очередь для выполнения задач. Управление потоком остатка будет позаботиться об этом на основе конфигурационных проходов в конструкторе, поэтому, если вы действительно уверены в параметрах конфигурации, вы можете пойти на это.
Теперь последнее, если вы не хотите использовать встроенную среду исполнителей Java, тогда вы можете спроектировать свое решение, используя BlockingQueue для хранения задач и запуска потока, который будет выполнять задачи из этой блокирующей очереди для выполнения. Ниже приведена реализация на высоком уровне:
class TaskRunner {
private int noOfThreads; //The no of threads which you want to run always
private boolean started;
private int taskQueueSize; //No. of tasks that can be in queue at a time, when try to add more tasks, then you have to wait.
private BlockingQueue<Runnable> taskQueue;
private List<Worker> workerThreads;
public TaskRunner(int noOfThreads, int taskQueueSize) {
this.noOfThreads = noOfThreads;
this.taskQueueSize = taskQueueSize;
}
//You can pass any type of task(provided they are implementing Runnable)
public void submitTask(Runnable task) {
if(!started) {
init();
}
try {
taskQueue.put(task);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void shutdown() {
for(Worker worker : workerThreads){
worker.stopped = true;
}
}
private void init() {
this.taskQueue = new LinkedBlockingDeque<>(taskQueueSize);
this.workerThreads = new ArrayList<>(noOfThreads);
for(int i=0; i< noOfThreads; i++) {
Worker worker = new Worker();
workerThreads.add(worker);
worker.start();
}
}
private class Worker extends Thread {
private volatile boolean stopped;
public void run() {
if(!stopped) {
try {
taskQueue.take().run();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
class Task1 implements Runnable {
@Override
public void run() {
//Your implementation for the task of type 1
}
}
class Task2 implements Runnable {
@Override
public void run() {
//Your implementation for the task of type 2
}
}
class Main {
public static void main(String[] args) {
TaskRunner runner = new TaskRunner(3,5);
runner.submitTask(new Task1());
runner.submitTask(new Task2());
runner.shutdown();
}
}
Оба вопроса действительно зависят от того, что находится внутри блока 'while (true) {}'. Это вращение, сон, блокировка ввода-вывода или что? – erickson
бессмысленно создавать пул потоков, но вы просто запускаете forever-loop для каждого потока. Для того, что вы собираетесь делать, вероятно, лучше подумать: иметь один выделенный поток для чтения из очереди.Всякий раз, когда он получает элемент, обработайте этот элемент, создав короткую задачу «Задача» и выполнив ее с пулом потоков. –
. Эй, @erickson: просто добавлено редактирование. В принципе, он будет спать или блокироваться в сети IO (я ожидаю, что вычисление будет минимальным) – Lycus