Java 工作线程发送到睡眠后CompletableFuture没有响应

Java 工作线程发送到睡眠后CompletableFuture没有响应,java,multithreading,java-8,executorservice,fork-join,Java,Multithreading,Java 8,Executorservice,Fork Join,我在努力了解消费的未来。 基本上,我向ConsumableFuture提供一个任务,然后将运行该任务的工作线程休眠2秒钟。我希望工作线程在2秒后恢复执行并返回结果 public class CompletableFutureDemo { public static void main(String[] args) { System.err.println("Application started");

我在努力了解消费的未来。 基本上,我向ConsumableFuture提供一个任务,然后将运行该任务的工作线程休眠2秒钟。我希望工作线程在2秒后恢复执行并返回结果

public class CompletableFutureDemo {

    public static void main(String[] args) {
        
        System.err.println("Application started");
        
        CompletableFuture
            .supplyAsync(()->work1())
            .thenAccept(op-> System.out.println(op));
        
        System.err.println("Application ended");
    }
    
    public static int work1() {
        System.out.println(Thread.currentThread().getName());
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("work1 called");
        return (int) (Math.random() * 100);
    }
}
输出:

Application started
ForkJoinPool.commonPool-worker-1
Application ended
为什么工作线程没有恢复

但是,如果我从工作线程中删除sleep语句,那么我将获得所需的输出

Application started
ForkJoinPool.commonPool-worker-1
work1 called
Application ended
64

正如@Slaw在注释中已经指出的,主线程完成并在工作线程处于睡眠状态时退出应用程序,因此您可以调用以使主线程保持等待,直到工作线程完成

System.err.println("Application started");

 CompletableFuture
            .supplyAsync(()->work1())
            .thenAccept(op-> System.out.println(op)).join();

System.err.println("Application ended");
输出:

ForkJoinPool.commonPool-worker-3
Application started
work1 called
12
Application ended
ForkJoinPool.commonPool-worker-3
Application started
Application ended
work1 called
25
或者,您可以让主线程在完成it工作后等待

  System.err.println("Application started");

  CompletableFuture<Void> completableFuture = CompletableFuture
            .supplyAsync(()->work1())
            .thenAccept(op-> System.out.println(op));

  System.err.println("Application ended");

  completableFuture.join();
如果您有多个CompletableFuture对象,则可以使用allOf等待所有任务完成,但在后台,每个CompletableTask都将异步执行

CompletableFuture.allOf(completableFuture1,completableFuture1).join();

正如@Slaw在注释中已经指出的,主线程完成并在工作线程处于睡眠状态时退出应用程序,因此您可以调用以使主线程保持等待,直到工作线程完成

System.err.println("Application started");

 CompletableFuture
            .supplyAsync(()->work1())
            .thenAccept(op-> System.out.println(op)).join();

System.err.println("Application ended");
输出:

ForkJoinPool.commonPool-worker-3
Application started
work1 called
12
Application ended
ForkJoinPool.commonPool-worker-3
Application started
Application ended
work1 called
25
或者,您可以让主线程在完成it工作后等待

  System.err.println("Application started");

  CompletableFuture<Void> completableFuture = CompletableFuture
            .supplyAsync(()->work1())
            .thenAccept(op-> System.out.println(op));

  System.err.println("Application ended");

  completableFuture.join();
如果您有多个CompletableFuture对象,则可以使用allOf等待所有任务完成,但在后台,每个CompletableTask都将异步执行

CompletableFuture.allOf(completableFuture1,completableFuture1).join();

通过提供自己的Executor实例,我实现了异步操作,并避免了将其标记为守护进程。遗嘱执行人的味道

CompletableFuture
            .supplyAsync(()->work1(), Executors.newFixedThreadPool(2))
            .thenAccept(op-> System.out.println(op));
我认为这可以避免创建守护进程线程,类似于我们在ExecutorServices中所做的


感谢@Slaw提供有关守护进程线程的信息。我想进一步了解为什么ForkJoin体系结构会在默认情况下将线程标记为守护进程。

通过提供自己的Executor实例,我实现了异步操作,并避免了将其标记为守护进程。遗嘱执行人的味道

CompletableFuture
            .supplyAsync(()->work1(), Executors.newFixedThreadPool(2))
            .thenAccept(op-> System.out.println(op));
我认为这可以避免创建守护进程线程,类似于我们在ExecutorServices中所做的


感谢@Slaw提供有关守护进程线程的信息。我想进一步了解为什么ForkJoin体系结构会在默认情况下将线程标记为守护进程。

公共fork-join池使用守护进程线程。您的应用程序正在退出,因为主线程(在本例中是唯一的非守护进程线程)在另一个线程完成之前退出。@Slaw感谢您提供的信息。Fork-join默认使用守护进程线程?有没有办法防止它们标记为守护进程?公共fork-join池使用守护进程线程。您的应用程序正在退出,因为主线程(在本例中是唯一的非守护进程线程)在另一个线程完成之前退出。@Slaw感谢您提供的信息。Fork-join默认使用守护进程线程?有没有办法防止它们标记为守护进程?CompletableFuture通常用于异步任务执行。假设我有4个任务分配给ForkJoinPool,而其他一些任务正在主线程上运行。join将阻塞主线程。这样的目的就会失败。解决此问题的任何替代方法?CompletableFuture通常用于异步任务执行。假设我有4个任务分配给ForkJoinPool,而其他一些任务正在主线程上运行。join将阻塞主线程。这样的目的就会失败。有没有其他方法可以解决这个问题?但如果您真的需要,我相信您可以使用返回守护进程线程的自定义线程工厂创建自己的ForkJoinPool。公共池无法做到这一点,因为否则开发人员将不得不手动关闭公共池,这对用户不友好。当然,按目前的情况,您不能关闭公共池。更正:…返回非守护进程线程的自定义线程工厂。但如果您确实需要它,我相信您可以使用返回守护进程线程的自定义线程工厂创建自己的ForkJoinPool。公共池无法做到这一点,因为否则开发人员将不得不手动关闭公共池,这对用户不友好。当然,照目前的情况,您不能关闭公共池。更正:…返回非守护进程线程的自定义线程工厂。