Springboot中的多線程

在Springboot中憾筏,針對多線程以及線程池,提供了@EnableAsync以及@Async兩個(gè)注解花鹅,只需要簡單配置即可完成多線程氧腰、線程池的開發(fā)。

1 線程池配置

Springboot提供了多線程的配置接口刨肃,只要實(shí)現(xiàn)該接口古拴,并使用@Configuration和@EnableAsync進(jìn)行注解,即可定義一個(gè)線程池之景。

@Configuration
@ComponentScan("com")
@EnableAsync
public class CustomMultiThreadingConfig implements AsyncConfigurer {
    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        //如果池中的實(shí)際線程數(shù)小于corePoolSize,無論是否其中有空閑的線程斤富,都會給新的任務(wù)產(chǎn)生新的線程
        taskExecutor.setCorePoolSize(5);
        //queueCapacity 線程池所使用的緩沖隊(duì)列
        taskExecutor.setQueueCapacity(256);
        //連接池中保留的最大連接數(shù)。
        taskExecutor.setMaxPoolSize(1024);
        //線程名稱前綴
        taskExecutor.setThreadNamePrefix("Application Thread-");
        taskExecutor.initialize();
        return taskExecutor;
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return AsyncConfigurer.super.getAsyncUncaughtExceptionHandler();
    }
}

ThreadPoolTaskExecutor的參數(shù):

  • int corePoolSize:線程池維護(hù)線程的最小數(shù)量.
  • int maximumPoolSize:線程池維護(hù)線程的最大數(shù)量.
  • long keepAliveTime:空閑線程的存活時(shí)間.
  • TimeUnit unit: 時(shí)間單位,現(xiàn)有納秒,微秒,毫秒,秒枚舉值.
  • BlockingQueue<Runnable> workQueue:持有等待執(zhí)行的任務(wù)隊(duì)列.
  • RejectedExecutionHandler handler: 用來拒絕一個(gè)任務(wù)的執(zhí)行锻狗,有兩種情況會發(fā)生這種情況满力。
    • 一是在execute方法中若addIfUnderMaximumPoolSize(command)為false焕参,即線程池已經(jīng)飽和;
    • 二是在execute方法中, 發(fā)現(xiàn)runState!=RUNNING || poolSize == 0,即已經(jīng)shutdown,就調(diào)用ensureQueuedTaskHandled(Runnable command)油额,在該方法中有可能調(diào)用reject叠纷。

2 定義異步任務(wù)

使用的方式非常簡單,一個(gè)標(biāo)注即可解決所有的問題:

@Async
public void demo() {
        ...
}

也可以將注解加到帶參數(shù)的方法上:

@Async
public void demo(int i) {
        ...
}

3 在線程中注入Bean的方法

在Springboot中定義多線程并不復(fù)雜潦嘶,網(wǎng)上能夠檢索的內(nèi)容很多涩嚣,基本誤導(dǎo)的東西很少。但實(shí)際開發(fā)中會遇到一些不易發(fā)現(xiàn)的問題掂僵。
個(gè)人使用場景時(shí)這樣的:

  • 自己實(shí)現(xiàn)了一個(gè)時(shí)序數(shù)據(jù)流計(jì)算的小框架
  • 不同的算法對應(yīng)的不同的計(jì)算任務(wù)航厚,也就是需要單獨(dú)啟動一個(gè)線程
  • 算法名稱和類名稱對應(yīng),通過反射機(jī)制啟動

但因?yàn)槊總€(gè)計(jì)算都是單獨(dú)啟動的線程锰蓬,由于業(yè)務(wù)邏輯較為復(fù)雜幔睬,在線程中需要@Autowired注入Bean,但在方法調(diào)用的時(shí)候芹扭,會拋出ava.lang.NullPointerException異常麻顶。

解決思路

針對上述問題的解決方法也很簡單——實(shí)現(xiàn) org.springframework.context.ApplicationContextAware接口
網(wǎng)上找到個(gè)鏈接,里面解釋的很好

https://www.cnblogs.com/codecat/p/11149893.html
“ApplicationContextAware的作用是可以方便獲取Spring容器ApplicationContext舱卡,從而可以獲取容器內(nèi)的Bean辅肾。ApplicationContextAware接口只有一個(gè)方法setApplicationContext,如果實(shí)現(xiàn)了這個(gè)方法轮锥,那么Spring創(chuàng)建這個(gè)實(shí)現(xiàn)類的時(shí)候就會自動執(zhí)行這個(gè)方法矫钓,把ApplicationContext注入到這個(gè)類中,也就是說舍杜,spring 在啟動的時(shí)候就需要實(shí)例化這個(gè) class(如果是懶加載就是你需要用到的時(shí)候?qū)嵗┓莺梗趯?shí)例化這個(gè) class 的時(shí)候,發(fā)現(xiàn)它包含這個(gè) ApplicationContextAware 接口的話蝴簇,sping 就會調(diào)用這個(gè)對象的 setApplicationContext 方法杯活,把 applicationContext Set 進(jìn)去了“敬剩”

代碼如下:

@Component
public class ApplicationContextProvider implements ApplicationContextAware {
    /**
     * 上下文對象
     */
    private static ApplicationContext applicationContext;

    /**
     * 設(shè)置上下文對象
     * @param applicationContext 應(yīng)用上下文
     * @throws BeansException Bean異常
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        ApplicationContextProvider.applicationContext = applicationContext;
    }

    /**
     * 獲取上下文對象
     *
     * @return application context
     */
    private static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    /**
     * 通過名稱獲取Bean.
     *
     * @param name Bean名稱
     * @return Object對象
     */
    public static Object getBean(String name) {
        return getApplicationContext().getBean(name);
    }

    /**
     * 通過類名獲取Bean.
     *
     * @param clazz 類名
     * @param <T> T
     * @return T
     */
    public static <T> T getBean(Class<T> clazz) {
        return getApplicationContext().getBean(clazz);
    }

    /**
     * 通過名稱以及Clazz返回指定的Bean
     *
     * @param name name
     * @param clazz class
     * @param <T> class
     * @return class
     */
    public static <T> T getBean(String name, Class<T> clazz) {
        return getApplicationContext().getBean(name, clazz);
    }
}

具體使用時(shí):

private DemoClass demoClass = ApplicationContextProvider.getBean(DemoClass.class);

這樣即完成了Bean的注入旁钧。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市互拾,隨后出現(xiàn)的幾起案子歪今,更是在濱河造成了極大的恐慌,老刑警劉巖颜矿,帶你破解...
    沈念sama閱讀 211,194評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件寄猩,死亡現(xiàn)場離奇詭異,居然都是意外死亡骑疆,警方通過查閱死者的電腦和手機(jī)田篇,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評論 2 385
  • 文/潘曉璐 我一進(jìn)店門替废,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人泊柬,你說我怎么就攤上這事椎镣。” “怎么了兽赁?”我有些...
    開封第一講書人閱讀 156,780評論 0 346
  • 文/不壞的土叔 我叫張陵状答,是天一觀的道長。 經(jīng)常有香客問我刀崖,道長惊科,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,388評論 1 283
  • 正文 為了忘掉前任亮钦,我火速辦了婚禮译断,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘或悲。我一直安慰自己,他們只是感情好堪唐,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評論 5 384
  • 文/花漫 我一把揭開白布巡语。 她就那樣靜靜地躺著,像睡著了一般淮菠。 火紅的嫁衣襯著肌膚如雪男公。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,764評論 1 290
  • 那天合陵,我揣著相機(jī)與錄音枢赔,去河邊找鬼。 笑死拥知,一個(gè)胖子當(dāng)著我的面吹牛踏拜,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播低剔,決...
    沈念sama閱讀 38,907評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼速梗,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了襟齿?” 一聲冷哼從身側(cè)響起姻锁,我...
    開封第一講書人閱讀 37,679評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎猜欺,沒想到半個(gè)月后位隶,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,122評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡开皿,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評論 2 325
  • 正文 我和宋清朗相戀三年涧黄,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了篮昧。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,605評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡弓熏,死狀恐怖恋谭,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情挽鞠,我是刑警寧澤疚颊,帶...
    沈念sama閱讀 34,270評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站信认,受9級特大地震影響材义,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜嫁赏,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評論 3 312
  • 文/蒙蒙 一其掂、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧潦蝇,春花似錦款熬、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至则酝,卻和暖如春殉簸,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背沽讹。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評論 1 265
  • 我被黑心中介騙來泰國打工般卑, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人爽雄。 一個(gè)月前我還...
    沈念sama閱讀 46,297評論 2 360
  • 正文 我出身青樓蝠检,卻偏偏與公主長得像,于是被迫代替她去往敵國和親挚瘟。 傳聞我的和親對象是個(gè)殘疾皇子蝇率,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評論 2 348