繁体   English   中英

CompletableFuture.thenApplyAsync 和 CompletableFuture.runAsync 与线程守护进程状态下自定义 ExecutorService 的区别

[英]Difference between CompletableFuture.thenApplyAsync and CompletableFuture.runAsync with custom ExecutorService in thread deamon status

我创建了一个测试类。 我有一个像这样创建的静态 ExecutorService:

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());
}

测试2

@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));
}

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

实际上问题是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 的线程加入主线程,因此您将获得异常。

如果你想异步运行一些后台任务并且不想从任务中返回任何东西,那么你可以使用 CompletableFuture.runAsync() 方法。 它接受一个 Runnable 对象并返回 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());
}

thenApplyAsync :- 周围没有其他线程,因此在当前主线程的上下文中调用 thenApplyAsync()

@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));
}

test 1 是守护线程,test2 不是守护线程。 希望你明白:(

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM