亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

@Async怎么用

發布時間:2021-07-07 18:36:57 來源:億速云 閱讀:219 作者:小新 欄目:編程語言

這篇文章主要為大家展示了“@Async怎么用”,內容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領大家一起研究并學習一下“@Async怎么用”這篇文章吧。

使用@Async注解的方法會新開一個線程去執行該方法,一些比較耗時的操作的操作使用該注解,交由Spring去管理線程的創建與銷毀。

接下來闡述一下自己的使用心得:
一、啟用@Async,個人在Springboot的啟動類加上以下注解

@EnableAsync

二、在需要進行異步操作的方法上加上@Async注解,注解不起作用的主要原因是被調用方法和調用方法處理同一個類中。 失效的代碼

class TestService {
    void a() { 
      this.b();
    }
	
    @Async
    void b(){}
}

正常的代碼

class TestService {
    void a(){ 
       BService.b();
    }
}

class BService() {
    @Async
    void b(){}
}

這個時候我們可能會想到AopContext.currentProxy(),這樣就可以在同一個方法里面調用了

class TestService {
	
   TestService getSelf() {
      return (TestService)AopContext.currentProxy();
   }
	
    void a() { 
      getSelf().b();
    }
	
    @Async
    void b(){}
}

在這里可能會拋出以下的異常,具體的原因及解決思路請參考這篇文章

java.lang.IllegalStateException: Cannot find current proxy:
Set 'exposeProxy' property on Advised to 'true' to make it available.

三、接下來了解一下@Async使用的線程池
@Async異步方法默認使用Spring創建ThreadPoolTaskExecutor(參考TaskExecutionAutoConfiguration),其中默認核心線程數為8,默認最大隊列和默認最大線程數都是Integer.MAX_VALUE。創建新線程的條件是隊列填滿時,而這樣的配置隊列永遠不會填滿,如果有@Async注解標注的方法長期占用線程(比如HTTP長連接等待獲取結果),在核心8個線程數占用滿了之后,新的調用就會進入隊列, 外部表現為沒有執行。
我們可以自定義一個線程池,線程數的設定需要考慮一下要執行的任務是IO密集型任務,還是CPU密集型任務。對于CPU密集型任務,如CPU核數+1;對于IO密集型任務,由于IO密集型任務線程并不是一直在執行任務,則應配置盡可能多的線程,如CPU核數*2。
接下來給出一個IO密集型任務的線程池配置代碼

@Configuration
public class ThreadPoolConfig {

    /**
     * 核心線程數
     */
    private static final int CORE_POOL_SIZE = Runtime.getRuntime().availableProcessors() * 2;

    /**
     * 最大線程數
     */
    private static final int MAX_POOL_SIZE = CORE_POOL_SIZE * 4 < 256 ? 256 : CORE_POOL_SIZE * 4;

    /**
     * 允許線程空閑時間(單位為秒)
     */
    private static final int KEEP_ALIVE_TIME = 10;

    /**
     * 緩沖隊列數
     */
    private static final int QUEUE_CAPACITY = 200;

    /**
     * 線程池中任務的等待時間,如果超過這個時候還沒有銷毀就強制銷毀
     */
    private static final int AWAIT_TERMINATION = 60;

    /**
     * 用來設置線程池關閉的時候等待所有任務都完成再繼續銷毀其他的Bean
     */
    private static final Boolean WAIT_FOR_TASKS_TO_COMPLETE_ON_SHUTDOWN = true;

    /**
     * 線程池名前綴
     */
    private static final String THREAD_NAME_PREFIX = "Spider-ThreadPool-";


    @Bean("spiderTaskExecutor")
    public ThreadPoolTaskExecutor spiderTaskExecutor () {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        taskExecutor.setCorePoolSize(CORE_POOL_SIZE);
        taskExecutor.setMaxPoolSize(MAX_POOL_SIZE);
        taskExecutor.setKeepAliveSeconds(KEEP_ALIVE_TIME);
        taskExecutor.setQueueCapacity(QUEUE_CAPACITY);
        taskExecutor.setThreadNamePrefix(THREAD_NAME_PREFIX);
        taskExecutor.setWaitForTasksToCompleteOnShutdown(WAIT_FOR_TASKS_TO_COMPLETE_ON_SHUTDOWN);
        taskExecutor.setAwaitTerminationSeconds(AWAIT_TERMINATION);
        /**
         * 拒絕策略 => 當pool已經達到max size的時候,如何處理新任務
         * CALLER_RUNS:不在新線程中執行任務,而是由調用者所在的線程來執行
         * AbortPolicy:直接拋出異常,這是默認策略;
         * DiscardOldestPolicy:丟棄阻塞隊列中靠最前的任務,并執行當前任務;
         * DiscardPolicy:直接丟棄任務;
         */
        taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        taskExecutor.initialize();
        return taskExecutor;
    }

}

線程池的使用

@Async("spiderTaskExecutor")

最后補充一些知識,要合理的控制線程數(比如采集訂單信息的同時要采集訂單詳情和文章信息,訂單詳情和文章信息可以合并在一個線程中處理),不要濫用。需要考慮什么時候使用MQ,什么時候開啟線程異步處理。推薦一個分析jstack文件的工具,IBM Thread and Monitor Dump Analyzer for Java,分析一下正在運行、發生死鎖、等待、阻塞的線程。

以上是“@Async怎么用”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

河西区| 博白县| 江达县| 木兰县| 温州市| 呼玛县| 宽城| 长寿区| 伊春市| 敦煌市| 商丘市| 珠海市| 西乌珠穆沁旗| 农安县| 吉安县| 襄汾县| 沁水县| 望谟县| 尉犁县| 上栗县| 措美县| 长治市| 双桥区| 兴仁县| 紫阳县| 屏山县| 车险| 山阳县| 古丈县| 仁化县| 菏泽市| 内乡县| 根河市| 克拉玛依市| 苗栗市| 信阳市| 扎兰屯市| 盐源县| 兴隆县| 阳东县| 迭部县|