简体   繁体   English

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

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

I have created a test class.我创建了一个测试类。 I have a static ExecutorService created like this:我有一个像这样创建的静态 ExecutorService:

private static ExecutorService service = Executors.newFixedThreadPool(4);

which I close with an @AfterClass function我用@AfterClass 函数关闭

@AfterClass
public static void afterClass(){
    service.shutdown();
    try {
        if (!service.awaitTermination(1000, TimeUnit.MILLISECONDS)){
            service.shutdownNow();
        }
    } catch (InterruptedException e) {
        service.shutdownNow();
    }
}

Now to my question have two test cases: Test1现在我的问题有两个测试用例: 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());
}

and

Test2测试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));
}

So my question is why in the first test the current thread is a deamon thread and in the second test is not?所以我的问题是为什么在第一个测试中当前线程是一个守护线程而在第二个测试中不是?

Actually the problem is that the exception that is thrown inside CompletableFuture.runAsync is ignored and since the test frameworks depend on exception to report test failure, the test seems to pass while it has not passed.实际上问题是CompletableFuture.runAsync抛出的异常被忽略了,并且由于测试框架依赖于异常来报告测试失败,测试似乎通过了但没有通过。 Add the following to your first test to make it throw exception:将以下内容添加到您的第一个测试中以使其抛出异常:

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

note that completableFuture.join() makes the thread running the Future to join the main thread and thus you will get the exception.请注意, completableFuture.join()使运行 Future 的线程加入主线程,因此您将获得异常。

If you want to run some background task asynchronously and don't want to return anything from the task, then you can use CompletableFuture.runAsync() method.如果你想异步运行一些后台任务并且不想从任务中返回任何东西,那么你可以使用 CompletableFuture.runAsync() 方法。 It takes a Runnable object and returns CompletableFuture.它接受一个 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 :- There is no other thread around so thenApplyAsync () is invoked in the context of current main thread 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 is a daemon thread and test2 is not daemon thread. test 1 是守护线程,test2 不是守护线程。 Hope so you understood :(希望你明白:(

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

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