Прерывание создания потоков при получении определённого результата
Есть вот такой кусок кода:
List<Node> nodes = generator.generateNodes(board);
int cores = Runtime.getRuntime().availableProcessors();
ExecutorService es = Executors.newFixedThreadPool(cores);
List<Future<Integer>> tasks = new CopyOnWriteArrayList<>();
try {
loop:
for(int i = 0; i < nodes.size(); i++) {
Future<Integer> score = es.submit
(new ArtIntel(nodes.get(i), Copier.deepCopy(board), level));
tasks.add(score);
for(Future<Integer> task: tasks) {
if(task.isDone() && task.get() > 500) {
System.out.println("Calculation interrupted in " +
Thread.currentThread());
break loop;
}
}
}
}
catch (InterruptedException exc) {
exc.printStackTrace();
}
catch (ExecutionException exc) {
exc.printStackTrace();
}
finally {
es.shutdown();
es.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
}
Можно ли как-то добиться, чтобы выполнялась проверка во вложенном цикле? Суть в том, чтобы ExecutorService перестал создавать новые потоки, если одним из предыдущих уже достигнут необходимый результат. Например: поток-1 стартует, затем поток-2 стартует (пока поток-1 ещё работает), далее поток-1 получает результат > 500 и поток-3, соответственно, вообще не создаётся. Код выше идею иллюстрирует, но, к сожалению, ничего не делает.
Дополнение
Вот такая картинка наблюдается в консоли:
Number of root nodes: 29
1400, 1400, 1400, 1400, 1200, 140, -1700, -1700, 1400, 1400, 1400, 1600, 1200, 140, 1400, 1400, 1400, 1400, 1400, 1200, 1400, 1400, 1400, 1400, 1400, 1400, 1200, 210, 1400,
а должно быть, по замыслу, например: 1400, 1400, (возможно, ещё 1-2 "проскочат" на обработку) и далее дефолтные(стартовые) значения у всех необработанных узлов. Процессор 2х-ядерный, так что и потоков одновременно только 2 и непонятно, почему проверочное условие не успевает срабатывать ("Calculation interrupted in " в консоли не появляется).
К тому же, ещё производится предварительная сортировка узлов генератором (1я строка кода) по потенциальной перспективности.
Ещё более наглядно:
Number of root nodes: 18
500, 500, 500, 500, 500, 500, 180, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, -2000,
Number of tasks given: 18
80, 40, 120, 120, 140, 60, 1200, 120, 140, 170, 120, 80, 100, 140, 140, 100, 170, -1500,
у всех узлов после 7го (с оценкой 1200) должны были остаться во второй строке те же значения, как и в первой, т.к. создание потоков для обработки следовало по условию прервать (не говоря о том, что вообще tasks должен быть в случае прерывания меньшего размера, чем nodes).
Ответы (1 шт):
Переписал следующим образом:
- Основной поток:
final int cores = Runtime.getRuntime().availableProcessors();
ExecutorService es = Executors.newFixedThreadPool(cores);
List<Future<Integer>> tasks = new ArrayList<>(nodes.size());
boolean stopped = false;
Interceptor f14 = new Interceptor(es, tasks, stopped);
try {
for(Node node: nodes) {
Future<Integer> score = es.submit
(new ArtIntel(node, Copier.deepCopy(board), level));
tasks.add(score);
}
f14.start();
}
finally {
if(!stopped){
es.shutdown();
es.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
f14.interrupt();
}
}
- Контроль прерывания (в отдельном классе):
@Override
public void run() {
while(!Thread.interrupted()) {
for(Future<Integer> task: tasks) {
try {
if(task.isDone() && task.get() > 500) {
for(Future<Integer> each: tasks) {
each.cancel(true);
}
es.shutdownNow();
es.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
stopped = true;
System.out.println("Interrupted in " +
Thread.currentThread());
}
}
catch (InterruptedException | ExecutionException exc) {
exc.printStackTrace();
Thread.currentThread().interrupt();
}
}
}
}