Java CompletableFuture.thenApplyAsync和CompletableFuture.runAsync之间的差异,自定义ExecutorService处于线程deamon状态

Java CompletableFuture.thenApplyAsync和CompletableFuture.runAsync之间的差异,自定义ExecutorService处于线程deamon状态,java,completable-future,Java,Completable Future,我已经创建了一个测试类。我创建了一个静态Executor服务,如下所示: private static ExecutorService service = Executors.newFixedThreadPool(4); 我用@AfterClass函数来结束它 @AfterClass public static void afterClass(){ service.shutdown(); try { if (!service.awaitTermination(1

我已经创建了一个测试类。我创建了一个静态Executor服务,如下所示:

private static ExecutorService service = Executors.newFixedThreadPool(4);
我用@AfterClass函数来结束它

@AfterClass
public static void afterClass(){
    service.shutdown();
    try {
        if (!service.awaitTermination(1000, TimeUnit.MILLISECONDS)){
            service.shutdownNow();
        }
    } catch (InterruptedException e) {
        service.shutdownNow();
    }
}
现在我的问题有两个测试用例: Test1

@Test
public void running_a_simple_asynchronous_stage(){
    CompletableFuture completableFuture = CompletableFuture.runAsync(()->{
        Assert.assertTrue(Thread.currentThread().isDaemon());
        sleepForMs(1000);
    }, service);
    Assert.assertFalse(completableFuture.isDone());
    sleepForMs(2000);
    Assert.assertTrue(completableFuture.isDone());
}

Test2

@Test
public void asynchronously_applying_a_function_on_previous_stage(){
    CompletableFuture completableFuture = CompletableFuture.completedFuture("astring").thenApplyAsync(str->{
        Assert.assertFalse(Thread.currentThread().isDaemon());
        sleepForMs(1000);
        return str.toUpperCase();
    }, service);
    Assert.assertFalse(completableFuture.isDone());
    Assert.assertNull(completableFuture.getNow(null));
    sleepForMs(2000);
    Assert.assertTrue(completableFuture.isDone());
    Assert.assertEquals("ASTRING", completableFuture.getNow(null));
}

所以我的问题是,为什么在第一个测试中,当前线程是deamon线程,而在第二个测试中不是?

如果要异步运行某个后台任务,并且不想从任务返回任何内容,那么可以使用CompletableFuture.runAsync()方法。它接受一个可运行的对象并返回CompletableFuture

@Test
public void running_a_simple_asynchronous_stage(){
    CompletableFuture completableFuture = CompletableFuture.runAsync(()->{
        Assert.assertTrue(Thread.currentThread().isDaemon());
        sleepForMs(1000);
    }, service);
    Assert.assertFalse(completableFuture.isDone());
    sleepForMs(2000);
    Assert.assertTrue(completableFuture.isDone());
}
然后应用同步:- 周围没有其他线程,因此在当前主线程的上下文中调用applyasync()

@Test
public void asynchronously_applying_a_function_on_previous_stage(){
    CompletableFuture completableFuture = CompletableFuture.completedFuture("astring").thenApplyAsync(str->{
        Assert.assertFalse(Thread.currentThread().isDaemon());
        sleepForMs(1000);
        return str.toUpperCase();
    }, service);
    Assert.assertFalse(completableFuture.isDone());
    Assert.assertNull(completableFuture.getNow(null));
    sleepForMs(2000);
    Assert.assertTrue(completableFuture.isDone());
    Assert.assertEquals("ASTRING", completableFuture.getNow(null));
}
测试1是守护进程线程,而测试2不是守护进程线程。
希望您能理解:(

事实上,问题是在
CompletableFuture.runAsync
中引发的异常被忽略,因为测试框架依赖异常来报告测试失败,所以测试似乎通过了,而它没有通过。将以下内容添加到第一个测试中,使其引发异常:

@Test
public void running_a_simple_asynchronous_stage() {
    CompletableFuture completableFuture = CompletableFuture.runAsync(() -> {
        Assert.assertTrue(Thread.currentThread().isDaemon());
        sleepForMs(1000);
    }, service);
    completableFuture.join();
    Assert.assertFalse(completableFuture.isDone());
    sleepForMs(2000);
    Assert.assertTrue(completableFuture.isDone());
}
请注意,
completableFuture.join()
使运行Future的线程加入主线程,因此您将得到异常