Можно ли дождаться основного потока, пока все потоки службы-исполнителя выполняют задачи? - PullRequest
0 голосов
/ 18 октября 2019

У меня есть сценарий вокруг вставки миллионов данных в бэкэнд и в настоящее время использую среду executor для загрузки этого. Я объясню мою проблему в более простых терминах.

В приведенном ниже случае у меня есть 10 запускаемых и три потока для выполнения одинаково. Учтите, что мой runnable выполняет операцию вставки, и для выполнения задачи требуется время. Когда я проверил, подразумевается, что, если все потоки заняты, другие задачи перейдут в очередь, и, как только потоки завершат выполнение задач, он получит задачи из пула и завершит их.

Таким образом, в этом случае будет создан объект SampleRunnable с 4 по 10, и он будет в пуле.

Проблема: поскольку мне нужно загрузить миллионы задач, я не могу загрузить все записи в очереди, которые могут привестик проблемам с памятью. Поэтому мой вопрос состоит в том, чтобы вместо того, чтобы брать все задачи в очередь, можно ли заставить основной поток ждать, пока какой-либо из рабочих потоков исполнителя не станет доступным.

Следуя подходам, которые я попытался обойти вместо постановки в очередьэто много задач:

Подход 1: Использовал очередь блокировки массива для исполнителя и задал размер как 5 (например, для)переведите в спящий режим на 1 минуту и ​​рекурсивно попытайтесь сделать то же самое. Это будет выполнено при любой повторной попытке, когда поток станет доступным.

Подход 2. Используется для выключения и ожидания завершения. то есть, если число задач 5, я закрываю и жду завершения. В блоке ожидающего завершения 'if' (executor.awaitTermination (60000, TimeUnit.SECONDS)) я снова создаю пул потоков.


public class SampleMain {

public static void main(String[] args) {

ExecutorService executor = Executors.newFixedThreadPool(3);

for (int i=0;i<10;i++){ 
   executorService.execute(new SampleRunnable(i));
}

executor.shutdown();
}

1 Ответ

0 голосов
/ 18 октября 2019

Похоже, проблема в том, что вы хотите ограничить основной поток, чтобы он не опередил рабочих. Если это так, тогда рассмотрите возможность явного создания экземпляра ThreadPoolExecutor вместо вызова Executors.newFixedThreadPool().

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

final int work_queue_size = 30;
BlockingQueue work_queue = new ArrayBlockingQueue(work_queue_size);
ExecutorService executor = new ThreadPoolExecutor(..., work_queue);

for (int i=0;i<10;i++){ 
    executorService.execute(new SampleRunnable(i));
}
...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...