| java核心技術(shù)總結(jié)八--多線程1、多線程程序在較低的層次上擴(kuò)展了多任務(wù)的概念: 一個(gè)程序同時(shí)執(zhí)行多個(gè)任務(wù)。通 java核心技術(shù)總結(jié)八--多線程 1、多線程程序在較低的層次上擴(kuò)展了多任務(wù)的概念: 一個(gè)程序同時(shí)執(zhí)行多個(gè)任務(wù)。通常,每一個(gè)任務(wù)稱為一個(gè)線程,它是線程控制的簡(jiǎn)稱??梢酝瑫r(shí)運(yùn)行一個(gè)以上線程的程序稱為多線程程序。 2、每個(gè)進(jìn)程擁有自己的一整套變量,而線程則共享數(shù)據(jù)。共享變量使線程之間的通信比進(jìn)程之間的通信更有效,更容易。 3、sleep方法是Thread類(lèi)的靜態(tài)方法,用于暫停當(dāng)前線程的活動(dòng),調(diào)用Thread.sleep()方法不會(huì)創(chuàng)建一個(gè)新線程。 4、并行運(yùn)行多個(gè)任務(wù)的操作: 1)、將任務(wù)代碼移到實(shí)現(xiàn)了Runnable接口的類(lèi)的run方法中 2)、創(chuàng)建一個(gè)類(lèi)對(duì)象 3)、由Runnable創(chuàng)建一個(gè)Thread對(duì)象 4)、啟動(dòng)線程 5、interrupt 、interrupted 和isInterrunpted的區(qū)別: interrupt方法是向線程發(fā)送中斷請(qǐng)求,線程的中斷狀態(tài)將被設(shè)置為true; interrupted方法是一個(gè)靜態(tài)方法,它檢測(cè)當(dāng)前的線程是否被中斷,而且調(diào)用interrupted方法會(huì)清除該線程的中斷狀態(tài).它將當(dāng)前線程的中斷狀態(tài)重置為false; isInterrupted方法是一個(gè)實(shí)例方法,可以用來(lái)檢驗(yàn)是否有線程被中斷,調(diào)用這個(gè)方法不會(huì)改變中斷狀態(tài) 6、線程狀態(tài): new(新生)? 用new thread()創(chuàng)建一個(gè)新線程 runnable(可運(yùn)行) 一旦調(diào)用start()方法,線程就處于runnable狀態(tài) blocked(被阻塞) waiting(等待) Timed waiting(計(jì)時(shí)等待) 當(dāng)線程處于被阻塞或者等待狀態(tài)時(shí),它暫時(shí)不活動(dòng),它不運(yùn)行任何代碼且消耗最少的資源,直到線程調(diào)度器重新激活它。 當(dāng)一個(gè)線程試圖獲取一個(gè)內(nèi)部的對(duì)象鎖,而該鎖被其他線程持有,則該線程進(jìn)入阻塞狀態(tài); 當(dāng)線程等待另一個(gè)線程通知調(diào)度器一個(gè)條件時(shí),它自己進(jìn)入等待狀態(tài)。 有幾個(gè)方法有一個(gè)超時(shí)參數(shù),調(diào)用它們導(dǎo)致線程進(jìn)入計(jì)時(shí)等待狀態(tài)。這一狀態(tài)將一直保持直到超時(shí)期滿或者接受到適當(dāng)?shù)耐ㄖ?。帶有超時(shí)參數(shù)的方法有:Thread.sleep,Object.wait,Thread.join,Lock.tryLock,Condition.await Terminated(被終止) 線程被終止的原因: 1)、因?yàn)閞un方法正常退出而自然死亡 2)、因?yàn)橐粋€(gè)沒(méi)有捕獲的異常終止了run方法而意外死亡 7、線程屬性: 1)、線程優(yōu)先級(jí):優(yōu)先級(jí)順序是從1到10; 2)、守護(hù)線程: 其唯一的好處是為其他線程提供服務(wù); 3)、線程組: 線程組類(lèi)實(shí)現(xiàn)Thread.UncaughtExceptionHandler接口。它的uncaughtException方法做如下操作: (1)、如果該線程組有父線程,則父線程組的uncaughtException方法被調(diào)用; (2)、否則,如果Thread.getDefaultExceptionHandler方法返回一個(gè)非空的處理器,則調(diào)用該處理器; (3)、否則,如果Throwable是ThreadDeath的一個(gè)實(shí)例,什么都不做; (4)、否則,線程的名字以及Throwable的棧蹤跡被輸出到System.err上; 4)、處理未捕獲異常的處理器 8、同步 8.1、鎖對(duì)象:ReentrantLock類(lèi)對(duì)象。 每一個(gè)對(duì)象有自己的ReentrantLock對(duì)象,如果兩個(gè)線程試圖訪問(wèn)同一個(gè)對(duì)象,那么鎖以串行的方式提供服務(wù)。  鎖是可重入的,因?yàn)榫€程可以重復(fù)的獲得已經(jīng)持有的鎖。鎖保持一個(gè)持有技術(shù)來(lái)跟蹤 對(duì)lock方法的嵌套調(diào)用。線程在每一個(gè)調(diào)用lock都要調(diào)用unlock來(lái)釋放鎖。 8.2、條件對(duì)象:通常線程進(jìn)入臨界區(qū),卻發(fā)現(xiàn)在某一條件滿足之后它才能執(zhí)行,要使用一個(gè)條件對(duì)象來(lái)管理那些已經(jīng)獲得了一個(gè)鎖但是卻不能做有用工作的線程。條件對(duì)象經(jīng)常被稱為條件變量。 一個(gè)鎖對(duì)象可以有一個(gè)或多個(gè)相關(guān)的條件對(duì)象,可以用newCondition方法獲得一個(gè)條件對(duì)象。當(dāng)方法的條件不能滿足時(shí),當(dāng)前線程被阻塞,并放棄了鎖。等待獲得鎖的線程和調(diào)用await方法的線程存在本質(zhì)上的區(qū)別。一旦一個(gè)線程調(diào)用await方法,它進(jìn)入該條件的等待集。當(dāng)鎖可用時(shí),該線程不能馬上解除阻塞。相反,它處于阻塞狀態(tài),直到另一個(gè)線程調(diào)用同一個(gè)條件上的signalAll方法時(shí)為止。 當(dāng)一個(gè)線程調(diào)用await時(shí),它沒(méi)有辦法重新激活自身。在對(duì)象的狀態(tài)有利于等待線程的方向改變時(shí)調(diào)用signalAll。signalAll不會(huì)立即激活一個(gè)等待線程,它僅僅解除等待線程的阻塞。 當(dāng)一個(gè)線程擁有某個(gè)條件的鎖時(shí),它僅僅可以在該條件上調(diào)用await,signalAll 或signal方法。 9、鎖和條件的關(guān)鍵之處: 1)、鎖用來(lái)保護(hù)代碼片段,任何時(shí)刻只能有一個(gè)線程執(zhí)行被保護(hù)的代碼 2)、鎖可以管理試圖進(jìn)入被保護(hù)代碼段的線程 3)、鎖可以擁有一個(gè)或多個(gè)相關(guān)的條件對(duì)象 4)、每個(gè)條件對(duì)象管理那些已經(jīng)進(jìn)入被保護(hù)的代碼段但還不能運(yùn)行的線程。 10、synchronized關(guān)鍵字 如果一個(gè)方法用synchronized關(guān)鍵字聲明,那么對(duì)象的鎖將保護(hù)整個(gè)方法。這個(gè)鎖也被稱為內(nèi)部對(duì)象鎖,它只有一個(gè)相關(guān)條件。wait方法添加一個(gè)線程到等待集中,notify/notifyAll方法解除等待線程的阻塞狀態(tài)。 wait、notifyAll以及notify方法是Object類(lèi)的final方法,它和Condition類(lèi)的方法await、signalAll和signal功能類(lèi)似。 內(nèi)部鎖和條件存在一些局限性: 1)、不能中斷一個(gè)正在試圖獲得鎖的線程; 2)、試圖獲得鎖時(shí)不能設(shè)定超時(shí); 3)、每個(gè)鎖僅有單一的條件,可能是不夠的。 11、使用synchronized和 lock/condition的建議: 1、最好既不用用lock/condition也不要使用synchronized關(guān)鍵字。在許多情況下可以使用java.util.concurrent包中的一種機(jī)制,它會(huì)處理所有的加鎖。 2、如果synchronized關(guān)鍵字適合你的程序,則盡量使用它,這樣可以減少編寫(xiě)的代碼數(shù)量,減少出錯(cuò)的幾率。 3、如果特別需要lock/condition結(jié)構(gòu)提供的獨(dú)有特性時(shí),才使用lock/condition. 12、同步阻塞 同步阻塞是另外一種獲得鎖的方式。 有時(shí)程序員使用一個(gè)對(duì)象的鎖來(lái)實(shí)現(xiàn)額外的原子操作,實(shí)際上稱為客戶端鎖定??蛻舳随i定是非常脆弱的,通常不推薦使用。 13、監(jiān)視器 1、監(jiān)視器具有的特性有: 監(jiān)視器是只包含私有域的類(lèi) 每個(gè)監(jiān)視器類(lèi)的對(duì)象有一個(gè)相關(guān)的鎖 使用該鎖對(duì)所有的方法進(jìn)行加鎖 該鎖可以有任意多個(gè)相關(guān)條件 2、java對(duì)象不同于監(jiān)視器的方面: 域不要求必須是private 方法不要求必須是synchronized 內(nèi)部鎖對(duì)客戶是可用的 14、同步格言: 如果向一個(gè)變量寫(xiě)入值,而這個(gè)變量接下來(lái)可能會(huì)被另外一個(gè)線程讀取,或者,從一個(gè)變量讀取,而這個(gè)變量可能是之前被另一個(gè)線程寫(xiě)入的,此時(shí)必須使用同步。 15、volatile volatile關(guān)鍵字為實(shí)例域的同步訪問(wèn)提供了一種免鎖機(jī)制,如果聲明一個(gè)域?yàn)関olatile,則編譯器和虛擬機(jī)就知道該域是可能被另外一個(gè)線程并發(fā)更新的。 volatile變量不能提供原子性 16、域的并發(fā)訪問(wèn)是安全的條件: 域是final,并且在構(gòu)造器調(diào)用完成之后被訪問(wèn) 對(duì)域的訪問(wèn)由公有的鎖進(jìn)行保護(hù) 域是volatile的 17、鎖測(cè)試和超時(shí) tryLock方法試圖申請(qǐng)一個(gè)鎖,在成功獲得鎖后返回true。否則返回false。tryLock允許程序打破死鎖。 18、讀寫(xiě)鎖 使用讀/寫(xiě)鎖的必要步驟: 構(gòu)造一個(gè)ReentrantReadWriteLock對(duì)象; 抽取讀鎖和寫(xiě)鎖; 對(duì)所有的訪問(wèn)者加讀鎖; 對(duì)所有的修改者加寫(xiě)鎖;寫(xiě)者線程必須是互斥訪問(wèn)的。 19、stop和suspend方法被棄用的原因 stop方法天生就不安全,該方法會(huì)終止所有未結(jié)束的方法,包括run方法。當(dāng)線程被終止,立即釋放它鎖住的所有對(duì)象的鎖。 suspend不會(huì)破壞對(duì)象,但是很容易造成死鎖。但是如果用suspend掛起一個(gè)持有一個(gè)鎖的線程,則該鎖在恢復(fù)之前是不可用的。如果調(diào)用suspend方法的線程試圖獲得同一個(gè)鎖,則程序死鎖。被掛起的線程等著被恢復(fù),而將其掛起的線程等待獲得鎖。 20、阻塞隊(duì)列 阻塞隊(duì)列的幾個(gè)變種: LinkedBlockingQueue: 容量沒(méi)有上邊界,但是可以選擇指定最大容量。它是一個(gè)雙端的版本。 ArrayBlockingQueue:在構(gòu)造時(shí)需要指定容量,并且有一個(gè)可選的參數(shù)來(lái)指定是否需要公平性。 PriorityBlockingQueue: 它是一個(gè)帶優(yōu)先級(jí)的隊(duì)列,而不是先進(jìn)先出隊(duì)列。元素按照它們的優(yōu)先級(jí)順序被移出。該隊(duì)列的容量沒(méi)有上界。 DelayQueue 阻塞隊(duì)列的方法: add???????? 添加一個(gè)元素。?????????????? ? ? ?? 如果隊(duì)列滿,則拋出異常 element? 返回隊(duì)列的頭元素。???????????????? 如果隊(duì)列空,拋出NoSuchElementException異常 offer? ? ? ? 添加一個(gè)元素并返回true。?????? 如果隊(duì)列滿,返回false peek ? ? ? 返回隊(duì)列的頭元素。???????????????? 如果隊(duì)列空,則返回null poll? ? ? ?? 移出并返回隊(duì)列的頭元素。??????? 如果隊(duì)列空,則返回null put? ? ? ?? 添加一個(gè)元素。?????????????????????? 如果隊(duì)列滿,則阻塞 remove?? 移出并返回頭元素。??????????????? 如果隊(duì)列空,則拋出異常 take??????? 移出并返回頭元素。??????????????? 如果隊(duì)列空,則阻塞 poll和peek方法返回空來(lái)指示失敗,因此向這些隊(duì)列中插入null值是非法的。 21、線程安全的集合 java.util.concurrent包提供了映像、有序集和隊(duì)列的高效實(shí)現(xiàn): ConcurrentHashMap、ConcurrentSkipListMap、 ConcurrentLinkedQueue。這些集合使用復(fù)雜的算法,通過(guò)允許并發(fā)的訪問(wèn)數(shù)據(jù)結(jié)構(gòu)不同的部分來(lái)使競(jìng)爭(zhēng)極小化。集合返回弱一致性的迭代器。 并發(fā)的散列映像表,可高效的支持大量的讀者和一定數(shù)量的寫(xiě)者。默認(rèn)情況下,假定可以有多達(dá)16個(gè)寫(xiě)者線程同時(shí)執(zhí)行。 ConcurrentHashMap和ConcurrentSkipListMap類(lèi)有相應(yīng)的方法用于原子性的關(guān)聯(lián)插入以及關(guān)聯(lián)刪除。putIfAbsent方法自動(dòng)地添加新的關(guān)聯(lián),前提是原來(lái)沒(méi)有這一關(guān)聯(lián)。 22、寫(xiě)數(shù)據(jù)的拷貝 CopyOnWriteArrayList和CopyOnWriteArraySet是線程安全的集合,其中所有的修改線程對(duì)底層數(shù)組進(jìn)行復(fù)制。 23、舊的線程安全的集合 Vector和Hashtable類(lèi)提供了線程安全的動(dòng)態(tài)數(shù)組和散列表的實(shí)現(xiàn)。在java1.2中,這些類(lèi)被棄用了,取而代之的是ArrayList和HashMap類(lèi)。這些類(lèi)不是線程安全的,而集合庫(kù)中提供了不同的機(jī)制。任何集合類(lèi)通過(guò)使用同步包裝器變成線程安全的。 24、執(zhí)行器 使用線程池的理由: 1、構(gòu)建一個(gè)新的線程是有一定代價(jià)的,因?yàn)樯婕芭c操作系統(tǒng)的交互。如果程序中創(chuàng)建了大量的生命期很短的線程,應(yīng)該使用線程池。一個(gè)線程池中包含許多準(zhǔn)備運(yùn)行的空閑線程。當(dāng)Runnable對(duì)象交給線程池,就會(huì)有一個(gè)線程調(diào)用run方法。當(dāng)run方法退出時(shí),線程不會(huì)死亡,而是在池中準(zhǔn)備為下一個(gè)請(qǐng)求提供服務(wù)。 2、減少并發(fā)線程的數(shù)目 25、執(zhí)行者工廠方法 方法???????????????????????????????????? ? ? ? ? 描述 newCachedThreadPool?????? 必要時(shí)創(chuàng)建新線程,空閑線程會(huì)被保留60秒 newFixedThreadPool?? 該池包含固定數(shù)量的線程,空閑線程會(huì)一直被保留 newSingleThreadExecutor? 只有一個(gè)線程的"池",該線程順序執(zhí)行每一個(gè)提交的任務(wù) newScheduledThreadPool?? 用于預(yù)定執(zhí)行而構(gòu)建的固定線程池,替代java.util.Timer newSingleThreadScheduledExecutor?? 用于預(yù)定執(zhí)行而構(gòu)建的單線程"池" 26、在使用線程池時(shí)應(yīng)該做的事情: 1)、調(diào)用Executors類(lèi)中靜態(tài)的方法newCachedThreadPool或newFixedThreadPool 2)、調(diào)用submit提交Runnable或callable對(duì)象 3)、如果想要取消一個(gè)任務(wù),或如果提交Callable對(duì)象,那就要保存好返回的Future對(duì)象 4)、當(dāng)不再提交任何任務(wù)時(shí),調(diào)用shutdown。 27、同步器 1)、fly信號(hào)量 2)、倒計(jì)時(shí)門(mén)栓 3)、障柵 4)、交換器。當(dāng)兩個(gè)線程在同一個(gè)數(shù)據(jù)緩沖區(qū)的兩個(gè)實(shí)例上工作的時(shí)候,就可以使用交換器。典型的情況是:一個(gè)線程向緩沖區(qū)填入數(shù)據(jù),另一個(gè)線程消耗這些數(shù)據(jù)。當(dāng)它們都完成以后,相互交換緩沖區(qū)。 5)、同步隊(duì)列。它是一種將生產(chǎn)者與消費(fèi)者線程配對(duì)的機(jī)制。當(dāng)一個(gè)線程調(diào)用SynchronousQueue的put方法時(shí),它會(huì)阻塞直到另一個(gè)線程調(diào)用take方法為止。 
 相關(guān)新聞 | 
|  | 
來(lái)自: 知識(shí)存儲(chǔ)館 > 《java》