Прерывание создания потоков при получении определённого результата

Есть вот такой кусок кода:

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 шт):

Автор решения: V-CHO

Переписал следующим образом:

  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();
        }
    }
  1. Контроль прерывания (в отдельном классе):
    @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();
                }
            }
        }       
    }
→ Ссылка