简体   繁体   中英

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:

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

which I close with an @AfterClass function

@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

@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

@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. 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.

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. It takes a Runnable object and returns 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

@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. Hope so you understood :(

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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