首頁 >Java >java教程 >Java非同步任務實作及分析

Java非同步任務實作及分析

PHPz
PHPz轉載
2023-04-22 20:49:061563瀏覽

一、什麼是非同步任務

無論是生活中或程式裡,大體可以分為兩種 : 同步與非同步。

同步:例如你去吃海底撈,你要先點鍋底,再點菜,然後服務員上鍋底,再上菜,最後你才能吃上菜,這一過程得按順序來。

非同步任務:還是去吃海底撈,吃的人很多,你前面有很多人,你可能要排隊,等到排到你才能再進入餐廳。但是如果中途你想去個廁所,怎麼辦,回來還要重新排隊。於是就有了叫號,你先排隊取號,然後你可以去按個摩,看個電影,做個 spa ,買杯奶茶 .... 。終於到你了,這時候會 通知 你排到了,然後你就能進去了。這個過程便是異步的。

二、SpringBoot Async

一開始想著開一個執行緒池,把任務丟到執行緒池裡去完成。

後來想起來SpringBoot 有一個比較方便的非同步框架Async

程式碼也很簡單,只需要在需要非同步執行的方法上加個@Async ,SpringBoot 啟動類別上加入  @EnableAsync即可

    @Async
    public void task() {
        // do something
    }

三、踩坑日記

程式碼雖然少,但是坑可不會隨著程式碼量的減少而減少。

為了方便起見,我本地搭了個demo,直接上代碼

@RestController
public class AsyncController {
    @Autowired
    private AsyncService asyncService;

    @GetMapping("/v1/say")
    public String sayV1() {
        asyncService.sayV1();
        return "success1";
    }

    @GetMapping("/v2/say")
    public String sayV2() {
        asyncService.sayV2();
        return "success2";
    }
}
@Service
public class AsyncService {
    public void sayV1() {
        try {
            Thread.sleep(3000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("hello world");
    }

    @Async
    public void sayV2() {
        try {
            Thread.sleep(3000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("hello world");
    }
}

很簡單的demo,提供兩個接口,/v1/say 和/v2/say,一個同步執行,一個非同步執行,透過sleep 3 秒來模擬耗時的任務

正常啟動,沒有任何問題,同步執行的等3 秒,主執行緒才會返回,非同步執行的立刻返回,等3 秒才會輸出helloworld

但是,當我加上斷點後,問題就產生了。

我先在 列印 hello world 那行加上個斷點,效果和原來的一樣,只是列印前被阻塞了,但不影響主執行緒的回傳。

Java非同步任務實作及分析

編輯

但當我把斷點加在方法進來的位置,發現 主執行緒居然被阻塞了!

Java非同步任務實作及分析

編輯

四、解決

各種問題排查,@Async 沒有生效,非同步任務等待主執行緒返回,都沒有找到有效的解決方法。

後來經過一個同事提醒,會不會是 debug 功能阻塞的執行緒呢?

抱著試一試的態度,我找到了debug 這邊的配置

Java非同步任務實作及分析

#編輯

斷點可以選擇阻塞jvm或是阻塞目前線程,預設是阻塞jvm。

將 suspend 選擇 Thread,便不會再阻塞主執行緒了

以上是Java非同步任務實作及分析的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:yisu.com。如有侵權,請聯絡admin@php.cn刪除