Я экспериментировал с Java 8 CompletableFutures. Насколько я понимаю, вызов CompletableFuture.supplyAsync (поставщик поставщика, исполнитель-исполнитель) всегда будет запускать задание в потоке, предоставленном переданным в Executor, но я заметил, что он иногда запускается в основном потоке, когда поставщик, которому я передаю это довольно "просто". Мой тестовый код:
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
public class SyncTest {
public static void main(String[] args) {
ExecutorService pool = Executors.newFixedThreadPool(5);
CompletableFuture<?>[] cfs = new CompletableFuture<?>[10];
AtomicInteger mainCount = new AtomicInteger();
for (int i = 0; i < cfs.length; i++) {
int index = i;
CompletableFuture<Integer> cf =
CompletableFuture.supplyAsync(() -> {
return index;
}, pool).thenApply(j -> {
if (Thread.currentThread().getName().equals("main")) {
mainCount.incrementAndGet();
}
System.out.println(Thread.currentThread().getName() + ": " + index + ": doing a heavy computation");
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
return j;
});
cfs[i] = cf;
}
System.out.println(Thread.currentThread().getName() + " doing other stuff");
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
CompletableFuture.allOf(cfs).join();
pool.shutdown();
System.out.println("Jobs on main: " + mainCount.get());
}
}
И результат, который я получаю, выглядит примерно так:
main: 0: doing a heavy computation
main: 1: doing a heavy computation
pool-1-thread-3: 2: doing a heavy computation
pool-1-thread-4: 3: doing a heavy computation
main: 4: doing a heavy computation
main doing other stuff
pool-1-thread-4: 9: doing a heavy computation
pool-1-thread-5: 8: doing a heavy computation
pool-1-thread-2: 7: doing a heavy computation
pool-1-thread-1: 6: doing a heavy computation
pool-1-thread-3: 5: doing a heavy computation
Jobs on main: 3
Я понимаю, что это довольно тривиальный пример, и что есть другие методы для CompletableFutures, такие как thenSupplyAsync и completedFuture, для работы с ними, мне более любопытно, как вообще возможно, что некоторые из этих задач выполняются в основном потоке.
Возможный дубликат CompletableFuture, supplyAsync () и thenApply ()




задача, которая печатает «выполнение тяжелых вычислений», вызывается с помощью thenApply, что означает, что вы не указали исполнителя для запуска этой задачи, и система может использовать любого исполнителя, включая текущий поток.
Если вы хотите, чтобы это задание выполнялось на предопределенном исполнителе, используйте вместо него thenApplyAsync, со вторым параметром - исполнителем или без него.
Отметьте ответы на этот вопрос: stackoverflow.com/questions/27723546/…