Как управлять потоками M (1 на задачу), обеспечение только N распараллеливает одновременно. С N <M. В Java

я использование, которое DateTime Сравнивают правильно?

Compare только предлагает информацию об относительном положении двух дат: меньше, равный или больше. То, что Вы хотите, является чем-то вроде этого:

if ((expiryDate - DateTime.Now).TotalDays < 30)
    matchFound = true;

Это вычитает два DateTime с. Результат TimeSpan объект, который имеет TotalDays свойство.

Кроме того, условное выражение может быть записано непосредственно как:

matchFound = (expiryDate - DateTime.Now).TotalDays < 30;

Никакой if необходимый.

5
задан user2427 12 September 2009 в 21:31
поделиться

4 ответа

Вы действительно можете использовать ExecutorService . Например, создайте новый фиксированный пул потоков с помощью метода newFixedThreadPool . Таким образом, помимо кэширования потоков, вы также гарантируете, что одновременно выполняется не более n потоков.

Что-то вроде этого:

private static final ExecutorService executor = Executors.newFixedThreadPool(N);
// ...
while (isOnJob) {
    List<JobTask> tasks = getJobTasks();
    if (!tasks.isEmpty()) {
        List<Future<?>> futures = new ArrayList<Future<?>>();
        for (final JobTask task : tasks) {
                Future<?> future = executor.submit(new Runnable() {    
                        @Override
                        public void run() {
                                task.doWork();
                        }
                });
                futures.add(future);
        }
        // you no longer need to use await
        for (Future<?> fut : futures) {
          fut.get();
        }
    }
}

Обратите внимание, что вам больше не нужно использовать защелку , поскольку get будет ждать завершения вычисления, если это необходимо.

7
ответ дан 13 December 2019 в 05:38
поделиться

Я согласен с JG, что ExecutorService - это то, что нужно ... но я думаю, что вы ' оба делают его более сложным, чем нужно.

Вместо того, чтобы создавать большое количество потоков (1 на задачу), почему бы просто не создать пул потоков фиксированного размера (с исполнителей. newFixedThreadPool (N) ) и передать ему все задачи? Не требуется семафор или что-то в этом роде - просто отправляйте задания в пул потоков по мере их получения, и пул потоков будет обрабатывать их с до N потоков за раз.

не собираетесь использовать более N потоков одновременно, зачем вам их создавать?

newFixedThreadPool (N) ) и передать ему все задачи? Не требуется семафор или что-то в этом роде - просто отправляйте задания в пул потоков по мере их получения, и пул потоков будет обрабатывать их с до N потоков за раз.

не собираетесь использовать более N потоков одновременно, зачем вам их создавать?

newFixedThreadPool (N) ) и передать ему все задачи? Не требуется семафор или что-то в этом роде - просто отправляйте задания в пул потоков по мере их получения, и пул потоков будет обрабатывать их с до N потоков за раз.

не собираетесь использовать более N потоков одновременно, зачем вам их создавать?

4
ответ дан 13 December 2019 в 05:38
поделиться

Используйте экземпляр ThreadPoolExecutor с несвязанной очередью и фиксированным максимальным размером потоков, например Executors.newFixedThreadPool (N) . Это позволит принять большое количество задач, но будет выполнять только N из них одновременно.

Если вместо этого вы выберете ограниченную очередь (с емкостью N ), то Executor отклонит выполнение задачи (насколько точно зависит от Политики, которую вы можете настроить при работе с ThreadPoolExecutor напрямую, вместо использования фабрики Executors - см. RejectedExecutionHandler ).

Если вам нужен «реальный» контроль перегрузки, вы должны установить границу BlockingQueue с емкостью N . Извлеките задачи, которые вы хотите выполнить, из базы данных и поместите их в очередь - если она заполнена, вызывающий поток заблокируется. В другом потоке (возможно, также начавшем использовать Executor API) вы берете задачи из BlockingQueue и отправляете их Executor . Если BlockingQueue пуст, вызывающий поток также будет заблокирован. Чтобы сигнализировать, что вы закончили, используйте «специальный» объект (например, синглтон, который отмечает последний / последний элемент в очереди).

В другом потоке (возможно, также начавшем использовать Executor API) вы берете задачи из BlockingQueue и отправляете их Executor . Если BlockingQueue пуст, вызывающий поток также будет заблокирован. Чтобы сигнализировать, что вы закончили, используйте «специальный» объект (например, синглтон, который отмечает последний / последний элемент в очереди).

В другом потоке (возможно, также начавшем использовать Executor API) вы берете задачи из BlockingQueue и отправляете их Executor . Если BlockingQueue пуст, вызывающий поток также будет заблокирован. Чтобы сигнализировать, что вы закончили, используйте «специальный» объект (например, синглтон, который отмечает последний / последний элемент в очереди).

1
ответ дан 13 December 2019 в 05:38
поделиться

Достижение хорошей производительности также зависит от типа работы, которая должна выполняться в потоках. Если ваша БД является узким местом в обработке, я бы начал обращать внимание на то, как ваши потоки обращаются к БД. Возможно, уместно использовать пул соединений. Это может помочь вам добиться большей пропускной способности, поскольку рабочие потоки могут повторно использовать соединения с БД из пула.

0
ответ дан 13 December 2019 в 05:38
поделиться