明輝手游網(wǎng)中心:是一個(gè)免費(fèi)提供流行視頻軟件教程、在線學(xué)習(xí)分享的學(xué)習(xí)平臺(tái)!

多線程設(shè)計(jì)重點(diǎn)

[摘要]1.多線程中有主內(nèi)存和工作內(nèi)存之分, 在JVM中,有一個(gè)主內(nèi)存,專門負(fù)責(zé)所有線程共享數(shù)據(jù);而每個(gè)線程都有他自己私有的工作內(nèi)存, 主內(nèi)存和工作內(nèi)存分貝在JVM的stack區(qū)和heap區(qū)。2.線程的狀態(tài)有'Ready', 'Running', 'Sleeping...
1.多線程中有主內(nèi)存和工作內(nèi)存之分, 在JVM中,有一個(gè)主內(nèi)存,專門負(fù)責(zé)所有線程共享數(shù)據(jù);而每個(gè)線程都有他自己私有的工作內(nèi)存, 主內(nèi)存和工作內(nèi)存分貝在JVM的stack區(qū)和heap區(qū)。

2.線程的狀態(tài)有'Ready', 'Running', 'Sleeping', 'Blocked', 和 'Waiting'幾個(gè)狀態(tài),
'Ready' 表示線程正在等待CPU分配允許運(yùn)行的時(shí)間。


3.線程運(yùn)行次序并不是按照我們創(chuàng)建他們時(shí)的順序來運(yùn)行的,CPU處理線程的順序是不確定的,如果需要確定,那么必須手工介入,使用setPriority()方法設(shè)置優(yōu)先級(jí)。

4.我們無從知道一個(gè)線程什么時(shí)候運(yùn)行,兩個(gè)或多個(gè)線程在訪問同一個(gè)資源時(shí),需要synchronized

5. 每個(gè)線程會(huì)注冊(cè)自己,實(shí)際某處存在著對(duì)它的引用,因此,垃圾回收機(jī)制對(duì)它就“束手無策”了。

6. Daemon線程區(qū)別一般線程之處是:主程序一旦結(jié)束,Daemon線程就會(huì)結(jié)束。

7. 一個(gè)對(duì)象中的所有synchronized方法都共享一把鎖,這把鎖能夠防止多個(gè)方法對(duì)通用內(nèi)存同時(shí)進(jìn)行的寫操作。synchronized static方法可在一個(gè)類范圍內(nèi)被相互間鎖定起來。

8. 對(duì)于訪問某個(gè)關(guān)鍵共享資源的所有方法,都必須把它們?cè)O(shè)為synchronized,否則就不能正常工作。

9. 假設(shè)已知一個(gè)方法不會(huì)造成沖突,最明智的方法是不要使用synchronized,能提高些性能。

10. 如果一個(gè)\"同步"方法修改了一個(gè)變量,而我們的方法要用到這個(gè)變量(可能是只讀),最好將自己的這個(gè)方法也設(shè)為 synchronized。

11. synchronized不能繼承, 父類的方法是synchronized,那么其子類重載方法中就不會(huì)繼承“同步”。

12. 線程堵塞Blocked有幾個(gè)原因造成:

(1)線程在等候一些IO操作
(2)線程試圖調(diào)用另外一個(gè)對(duì)象的“同步”方法,但那個(gè)對(duì)象處于鎖定狀態(tài),暫時(shí)無法使用。

13.原子型操作(atomic), 對(duì)原始型變量(primitive)的操作是原子型的atomic. 意味著這些操作是線程安全的, 但是大部分情況下,我們并不能正確使用,來看看 i = i + 1 , i是int型,屬于原始型變量:

(1)從主內(nèi)存中讀取i值到本地內(nèi)存.
(2)將值從本地內(nèi)存裝載到線程工作拷貝中.
(3)裝載變量1.
(4)將i 加 1.
(5)將結(jié)果給變量i.
(6)將i保存到線程本地工作拷貝中.
(7)寫回主內(nèi)存.

注意原子型操作只限于第1步到第2步的讀取以及第6到第7步的寫, i的值還是可能被同時(shí)執(zhí)行i=i+1的多線程中斷打擾(在第4步)。

double 和long 變量是非原子型的(non-atomic)。數(shù)組是object 非原子型。



14. 由于13條的原因,我們解決辦法是:

class xxx extends Thread{

//i會(huì)被經(jīng)常修改
private int i;

public synchronized int read(){ return i;}

public synchronized void update(){ i = i + 1;}

..........

}

15. Volatile變量, volatile變量表示保證它必須是與主內(nèi)存保持一致,它實(shí)際是"變量的同步", 也就是說對(duì)于volatile變量的操作是原子型的,如用在long 或 double變量前。


16. 使用yield()會(huì)自動(dòng)放棄CPU,有時(shí)比sleep更能提升性能。

17. sleep()和wait()的區(qū)別是:wait()方法被調(diào)用時(shí)會(huì)解除鎖定,但是我們能使用它的地方只是在一個(gè)同步的方法或代碼塊內(nèi)。

18. 通過制造縮小同步范圍,盡可能的實(shí)現(xiàn)代碼塊同步,wait(毫秒數(shù))可在指定的毫秒數(shù)可退出wait;對(duì)于wait()需要被notisfy()或notifyAll()踢醒。

19. 構(gòu)造兩個(gè)線程之間實(shí)時(shí)通信的方法分幾步:
(1). 創(chuàng)建一個(gè)PipedWriter和一個(gè)PipedReader和它們之間的管道;
PipedReader in = new PipedReader(new PipedWriter())
(2). 在需要發(fā)送信息的線程開始之前,將外部的PipedWriter導(dǎo)向給其內(nèi)部的Writer實(shí)例out
(3). 在需要接受信息的線程開始之前,將外部的PipedReader導(dǎo)向給其內(nèi)部的Reader實(shí)例in
(4). 這樣放入out的所有東西度可從in中提取出來。

20. synchronized帶來的問題除性能有所下降外,最大的缺點(diǎn)是會(huì)帶來死鎖DeadLock,只有通過謹(jǐn)慎設(shè)計(jì)來防止死鎖,其他毫無辦法,這也是線程難以馴服的一個(gè)原因。不要再使用stop() suspend() resume()和destory()方法

21. 在大量線程被堵塞時(shí),最高優(yōu)先級(jí)的線程先運(yùn)行。但是不表示低級(jí)別線程不會(huì)運(yùn)行,運(yùn)行概率小而已。

22. 線程組的主要優(yōu)點(diǎn)是:使用單個(gè)命令可完成對(duì)整個(gè)線程組的操作。很少需要用到線程組。

23. 從以下幾個(gè)方面提升多線程的性能:

檢查所有可能Block的地方,盡可能的多的使用sleep或yield()以及wait();

盡可能延長sleep(毫秒數(shù))的時(shí)間;

運(yùn)行的線程不用超過100個(gè),不能太多;

不同平臺(tái)linux或windows以及不同JVM運(yùn)行性能差別很大。

24. 推薦幾篇相關(guān)英文文章:



Use Threading Tricks to Improve Programs