簡體   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