用在哪:多線程用來(lái)干啥的
- 一個(gè)任務(wù)分為多個(gè)子任務(wù)治宣,并行執(zhí)行火的,提高該任務(wù)執(zhí)行效率州袒,比如要給目標(biāo)列表推送消息,可以用多個(gè)線程來(lái)并行發(fā)消息坦报。
- 在主線程中異步執(zhí)行其他任務(wù),避免串行執(zhí)行的等待狂鞋。比如處理完交易后的發(fā)消息通知片择,可以提交發(fā)通知任務(wù)給線程池進(jìn)行異步處理,減少主任務(wù)響應(yīng)時(shí)間
怎么用:怎么使用多線程
- 實(shí)現(xiàn)Runnable或者Callable接口(需要獲取任務(wù)的返回值時(shí)使用)來(lái)定義任務(wù)job骚揍,一般不使用繼承Thread類字管,實(shí)際使用多半是定義任務(wù)將其提交線程池來(lái)執(zhí)行。一般在demo測(cè)試api時(shí)使用繼承Thread
- 將job提交給線程池來(lái)執(zhí)行信不, 線程池創(chuàng)建主要以下幾種方式
- 使用ThreadPoolExecutor:
ThreadPoolExecutor executor=new ThreadPoolExecutor(
int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler);
- 使用Executors:
#按需創(chuàng)建線程的執(zhí)行器
ExecutorService executor=Executors.newCachedThreadPool() ;
#單一線程執(zhí)行器
ExecutorService executor=Executors.newSingleThreadExecutor() ;
#固定大小的執(zhí)行器
ExecutorService executor=Executors.newFixedThreadPool(int nThreads);
#可調(diào)度的執(zhí)行器
ExecutorService executor=Executors.newScheduledThreadPool(
int corePoolSize, ThreadFactory threadFactory) ;
將任務(wù)提交給線程池執(zhí)行 exector.submit(job)嘲叔。當(dāng)是callable 任務(wù)時(shí)可以獲取返回Future 或者ScheduledFuture用來(lái)查詢?nèi)蝿?wù)執(zhí)行狀態(tài)和執(zhí)行結(jié)果
也可以使用spring自帶的異步任務(wù)。在配置類上注解@EnableAsync 開啟spring的異步任務(wù)浑塞,在需要異步執(zhí)行的方法上用@Async即可異步執(zhí)行任務(wù)借跪。
為什么:為什么要用多線程
- 常見web場(chǎng)景都是cpu運(yùn)算較快,cpu經(jīng)常大量時(shí)間用在等待io上等待(比如網(wǎng)絡(luò)io酌壕,文件io)掏愁,使用多線程,減少cpu的等待io時(shí)間卵牍,充分利用cpu的計(jì)算性能果港。
注意事項(xiàng)
多線程安全:多線程并發(fā)訪問共享資源會(huì)存在線程安全問題,將在下一篇講到,因此在多線程編程特別注意共享資源的使用糊昙。
盡量避免繼承Thread類創(chuàng)建線程辛掠,多使用線程池,減少頻繁創(chuàng)建和銷毀線程帶來(lái)的開銷释牺。
線程的數(shù)量應(yīng)該看需求設(shè)置合理的數(shù)值萝衩。避免線程設(shè)置過(guò)大或者過(guò)小。過(guò)大將帶來(lái)很大的上下文切換開銷没咙,消耗更多內(nèi)存猩谊。過(guò)小則浪費(fèi)cpu。一般推薦:Nthread = Ncpu * Ucpu *(1+W/C)祭刚,各字段含義:Nthreads:線程數(shù)量牌捷;Ncpu:CPU的數(shù)量墙牌;Ucpu:CPU使用率,范圍在[0,1]暗甥;W/C:等待時(shí)間與計(jì)算時(shí)間的比率
分清是計(jì)算密集型還是IO密集型喜滨,如果是C無(wú)限大也就是計(jì)算密集型的那么線程太多意義不大,因?yàn)樾枰狢PU計(jì)算撤防,起多了也沒用,一般n+1虽风。如果是IO密集型那么可以起更多的線程,因?yàn)榈却龝r(shí)間過(guò)多,一般2n+1或者3n+1
Stream的parallelStream方法是多線程處理(這個(gè)較容易被忽視)寄月。注意使用時(shí)的并發(fā)訪問共享資源帶來(lái)的安全問題