☆技術(shù)問(wèn)答集錦(12)并發(fā)編程-任務(wù)執(zhí)行

1 串行執(zhí)行的缺點(diǎn)?

代碼串行執(zhí)行,同步等待時(shí)間較長(zhǎng),CPU利用率低,造成糟糕的響應(yīng)性和吞吐量;

2 每一個(gè)任務(wù)創(chuàng)建一個(gè)線程的不足?

  1. 線程生命周期開銷非常高;
  2. 資源消耗:當(dāng)可運(yùn)行線程數(shù)多于可用處理器的數(shù)量,會(huì)有線程閑置占用內(nèi)存,且大量線程競(jìng)爭(zhēng)CPU導(dǎo)致性能開銷;
  3. 穩(wěn)定性:不同平臺(tái)可創(chuàng)建線程的數(shù)量有限制;

3 為什么要用線程池,如何合理的設(shè)置線程數(shù)量?

  1. 限制系統(tǒng)中使用線程的數(shù)量以及更好的使用線程;
  2. 減少線程創(chuàng)建和銷毀的次數(shù),使線程可以多次復(fù)用;
  3. 根據(jù)系統(tǒng)情況,調(diào)整線程的數(shù)量。防止創(chuàng)建過(guò)多的線程,消耗過(guò)多的內(nèi)存;

確認(rèn)APP類型(N為CPU總合數(shù)):(1)CPU密集型:線程池大小設(shè)置為N+1;(2)IO密集型:線程池大小設(shè)置為2N+1;

一個(gè)估算公式:最佳線程數(shù)目 = (線程等待時(shí)間與線程CPU時(shí)間之比 + 1)* CPU數(shù)目;

線程等待時(shí)間所占比例越高,需要越多線程。線程CPU時(shí)間所占比例越高,需要越少線程

一個(gè)系統(tǒng)最快的部分是CPU,所以決定一個(gè)系統(tǒng)吞吐量上限的是CPU。增強(qiáng)CPU處理能力,可以提高系統(tǒng)吞吐量上限。但根據(jù)短板效應(yīng),真實(shí)的系統(tǒng)吞吐量并不能單純根據(jù)CPU來(lái)計(jì)算。那要提高系統(tǒng)吞吐量,就需要從“系統(tǒng)短板”(比如網(wǎng)絡(luò)延遲、IO)著手:

(1)盡量提高短板操作的并行化比率,比如多線程下載技術(shù);

(2)增強(qiáng)短板能力,比如用NIO替代IO;

第(1)條聯(lián)系到Amdahl定律,這條定律定義了串行系統(tǒng)并行化后的加速比計(jì)算公式:

加速比=優(yōu)化前系統(tǒng)耗時(shí) / 優(yōu)化后系統(tǒng)耗時(shí)

加速比越大,表明系統(tǒng)并行化的優(yōu)化效果越好。Addahl定律還給出了系統(tǒng)并行度、CPU數(shù)目和加速比的關(guān)系,加速比為Speedup,系統(tǒng)串行化比率(指串行執(zhí)行代碼所占比率)為F,CPU數(shù)目為N:

Speedup <= 1 / (F + (1-F)/N)

當(dāng)N足夠大時(shí),串行化比率F越小,加速比Speedup越大。其他詳細(xì)內(nèi)容,請(qǐng)參考《如何合理地估算線程池大???》

4 如何計(jì)算JVM可創(chuàng)建線程的最大數(shù)量?

首先要說(shuō)明一點(diǎn),Java線程的實(shí)現(xiàn)是基于底層系統(tǒng)的線程機(jī)制來(lái)實(shí)現(xiàn)的,程序中開的線程并不全部取決于JVM虛擬機(jī)棧,而是取決于CPU,操作系統(tǒng),其他進(jìn)程,Java的版本。JVM的線程與計(jì)算機(jī)本身性能相關(guān)。

在不考慮系統(tǒng)本身限制的情況下,主要跟JVM一下幾點(diǎn)有關(guān):

-Xms 初始堆大小 (在實(shí)際生產(chǎn)中,一般把-Xms和-Xmx設(shè)置成一樣的。)

-Xmx 最大堆大小

-Xss 每個(gè)線程棧大小

結(jié)論1:當(dāng)給JVM的堆內(nèi)存分配的越大,系統(tǒng)可創(chuàng)建的線程數(shù)量就越少;

結(jié)論2:當(dāng)-Xss的的值越小,可生成的線程數(shù)量就越多,JDK5以下默認(rèn)好像是256K,以上默認(rèn)為1M;

總結(jié):線程最大數(shù)量由JVM的堆(-Xmx,-Xms)大小、Thread的棧(-Xss)內(nèi)存大小、系統(tǒng)最大可創(chuàng)建的線程數(shù)的限制參數(shù)三個(gè)方面影響。不考慮系統(tǒng)限制,可以通過(guò)這個(gè)公式估算:

線程數(shù)量 = (機(jī)器本身可用內(nèi)存 - JVM分配的堆內(nèi)存) / Xss的值。

5 Runnable是接口還是類?為什么Runnable接口可以new?接口中方法、變量默認(rèn)修飾符?

Runnable是接口,因?yàn)閚ew Runnable接口產(chǎn)生的是一個(gè)匿名內(nèi)部類,接口中的變量的修飾符默認(rèn)為public static final;接口中的方法的修飾符默認(rèn)為public abstract;

接口是一種高度抽象的模版,接口中的成員變量是模版的一部分,其接口的實(shí)現(xiàn)類必須共有這些成員變量,所以成員變量的修飾符默認(rèn)為public、static、final。static使得實(shí)現(xiàn)這個(gè)接口的類,可以直接使用這個(gè)變量。如果是非靜態(tài)變量,那么接口的多個(gè)實(shí)現(xiàn)類可能出現(xiàn)變量名重名的現(xiàn)象。final表示被修飾的變量為常數(shù),不可以修改。一個(gè)既是static又是final的字段表示只占據(jù)一段不能改變的存儲(chǔ)空間。如果是非final變量,那么接口的實(shí)現(xiàn)類可以修改變量的值,這與抽象類沒(méi)有區(qū)別了。由于接口起到標(biāo)準(zhǔn)化和規(guī)范化的作用,所以其成員變量默認(rèn)修飾符為static、final。

6 execute方法調(diào)用后,任務(wù)會(huì)何時(shí)執(zhí)行?

ThreadPoolExecutor.execute() => addWorker()

7 如果自己設(shè)計(jì)任務(wù)執(zhí)行框架,要考慮哪些方面?

  1. 在什么(What)線程中執(zhí)行任務(wù)?
  2. 任務(wù)按照什么(What)順序執(zhí)行(優(yōu)先級(jí))?
  3. 有多少個(gè)(How Many)任務(wù)能并發(fā)執(zhí)行?
  4. 在隊(duì)列中有多少個(gè)(How Many)任務(wù)在等待執(zhí)行?
  5. 系統(tǒng)該怎么(How)拒絕任務(wù)?
  6. 在任務(wù)執(zhí)行前后,應(yīng)該進(jìn)行哪些(What)動(dòng)作?

8 Timer執(zhí)行任務(wù)會(huì)有什么缺點(diǎn)?

  1. Timer執(zhí)行定時(shí)任務(wù)只會(huì)創(chuàng)建一個(gè)線程。
  2. Timer是基于絕對(duì)時(shí)間的調(diào)度機(jī)制,對(duì)系統(tǒng)時(shí)間敏感。
  3. Timer存在線程泄露問(wèn)題(Timer不捕獲異常,當(dāng)拋出一個(gè)未檢查異常時(shí)線程將終止)。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容