java - Future.get 无法阻塞 forkjoinpool/workstealingpool 中的线程

标签 java concurrency block future forkjoinpool

我把workstealingpool的大小设置为1,看来future.get()并没有阻塞线程。

@Test
public void runAsyncThenApplyExample() {
    ExecutorService executor = Executors.newWorkStealingPool(1);
    CompletableFuture cf = CompletableFuture.supplyAsync(
            () -> {
                //assertTrue(Thread.currentThread().isDaemon());
                System.out.println("func: " + threadName());
                Callable<Long> callable = () ->stub();
                Future<Long> future = executor.submit(callable);
                try {
                    future.get();  <<<<< **I think this should block the thread**
                } catch (InterruptedException | ExecutionException e) {
                    e.printStackTrace();
                }
                return 1;
            }, executor).thenAccept(s -> {
        System.out.println("accept: " + threadName());
    });
    //assertFalse(cf.isDone());
    System.out.println("main: " + threadName());
    sleep(10);
    assertTrue(cf.isDone());
}

private Long stub() {
    System.out.println("stub: " + threadName());
    return 1L;
}
private String threadName() {
    return Thread.currentThread().getName();
}

输出:

func: ForkJoinPool-1-worker-3
main: main
stub: ForkJoinPool-1-worker-3
accept: ForkJoinPool-1-worker-3

似乎 Future.get() 和 stub 使用的是同一个 threead。 enter image description here

enter image description here

最佳答案

Executors.newWorkStealingPool(1); 使用 ForkJoinPool,它有一个未记录的功能,称为补偿线程。

来自 http://www.coopsoft.com/ar/CalamityArticle.html (强调我的):

Introduced with JDK1.8 is the CompletableFuture Class. To quote the JavaDoc:

“A Future that may be explicitly completed (setting its value and status), and may include dependent functions and actions that trigger upon its completion.”

Not mentioned in the JavaDoc is that when using a large number of dependent functions with a get() method, the framework creates “compensation threads” to continue fetching application tasks from the deques and submission queue.

因此,当您执行 future.get(); 时,它会阻塞,但会创建另一个线程来执行任务。

当运行你的代码时,我得到的输出是:

func: ForkJoinPool-1-worker-1
main: main
stub: ForkJoinPool-1-worker-0
accept: ForkJoinPool-1-worker-1

您还没有显示您的 threadName() 方法,可能其中有错误,因此您看到了相同的线程名称(或者您使用了使用相同名称的不同 JVM在这种情况下,检查线程 ID)?如果没有,请提供将 func 和 stub 作为相同线程输出的完整代码。

关于java - Future.get 无法阻塞 forkjoinpool/workstealingpool 中的线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56233669/

相关文章:

java - "delegation"如何帮助线程安全类?

ios - 仅在准备好时才返回方法?

Objective-C self->_ivar 访问显式与隐式 self->

java - Spring Boot 应用程序未在现有 tomcat 上完全启动

java - Spring boot @Scheduled 失败 SQL 错误 : 17008, SQLState: 08003

java - 当多个线程同时请求加载同一个类时会发生什么?

html - <a> 元素的显示 block

java - 使用 Oauth 连接到 Google Compute Engine

java - 连接到 Docker 容器中的 H2 数据库

java - 与 HikariCP 的并发