【发布时间】:2022-01-18 20:00:01
【问题描述】:
如果 ForkJoinPool 中的线程执行阻塞 I/O 活动(在下面的代码中使用 Thread.sleep(10000) 模拟),它应该选择另一个不会导致阻塞 IO 的任务。
但是,使用 ForkJoinPool 以 1 或 2 的并行度运行以下代码,结果与它不匹配。线程不会放弃阻塞任务(即任务 1 和任务 2)并移动到非阻塞任务(任务 3)。
在 pool size =1 的情况下,所有任务按顺序执行,而我希望 Task 3 首先完成,因为它在两种情况下都是非阻塞的( pool size=1 或 2)
在阻塞 IO 的情况下,ForkJoinPool 中线程的实际行为是什么?
ForkJoinPool pool = new ForkJoinPool(1);
List<Future<String>> tasks = new ArrayList<Future<String>>();
//Blocking
tasks.add(pool.submit(() -> { Thread.sleep(10000); System.out.println("Task 1 woke up"+ Thread.currentThread().isDaemon()); return "task1"; }));
//Blocking
tasks.add(pool.submit(() -> { Thread.sleep(10000); System.out.println("Task 2 woke up"+Thread.currentThread().isDaemon()); return "task2"; }));
//Non Blocking
tasks.add(pool.submit(() -> { System.out.println("Task 3 Runs"+Thread.currentThread().isDaemon()); return "task3"; }));
int i=0;
System.out.println("pool size = " + pool.getParallelism() + "Thread count=" +pool.getPoolSize() + "Stealing =" + pool.getStealCount());
System.out.println("waiting");
String str1 = tasks.get(0).get();
String str2 = tasks.get(1).get();
String str3 = tasks.get(2).get();
System.out.println("Results = " + str1+ str2 +str3);
System.out.println("done");
结果:
//池大小 = 2
任务 2 已唤醒真实
任务 1 已唤醒真实
任务 3 运行为真
//池大小=1
任务 1 已唤醒真实
任务 2 已唤醒真实
任务 3 运行为真
另一个观察:
当我们首先提交任务 3(非阻塞)时,只有它首先被调用。
【问题讨论】:
-
什么版本的Java?就像您希望实施纤维一样?
-
嗨,Nathan,它的 Java 15。我希望 ForkJoinPool 中的线程在当前分配的任务执行一些 IO 时切换到非阻塞任务。根据 Project Loom ,ForkJoinPool 将用于 Fibers,因此期望它会以这种方式运行。 cr.openjdk.java.net/~rpressler/loom/Loom-Proposal.html
标签: java multithreading executorservice thread-sleep forkjoinpool