核心技術unit15 javase多線程_第1頁
核心技術unit15 javase多線程_第2頁
核心技術unit15 javase多線程_第3頁
核心技術unit15 javase多線程_第4頁
核心技術unit15 javase多線程_第5頁
已閱讀5頁,還剩25頁未讀, 繼續(xù)免費閱讀

付費下載

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領

文檔簡介

JavaSE回顧關鍵字ThreadRunStartJoinSynchronizedLock課程目標線程同步線程通信線程池線程相關類多線程線程同步線程安全問題銀行取錢問題,兩個人同時從一個賬戶中取錢(或存錢)見/geminno/thread2/Account.java/geminno/thread2/DrawThread.java/geminno/thread2/DrawTest.java同步代碼塊?

上面問題的出現(xiàn)是由于run()方法的方法體不具有同步安全性--程序中有兩個并發(fā)的線程在修改同一個Account對象,由于兩個線程的切換時間不致而導致問題出現(xiàn)為了解決上面的問題,Java的多線程支持引入了用監(jiān)視器來解決這個問題線程同步同步監(jiān)視器用法就是同步代碼塊,格式如下:synchronized(obj){...//需要同步的代碼}synchronized后obj就是同步監(jiān)視器代碼的含意是:線程開始執(zhí)行同步代碼塊之前,必須先獲得對同步監(jiān)視器的鎖定注意:任何時刻只能有一個線程可以獲得對同步監(jiān)視器的鎖定,當同步代碼塊執(zhí)行完成后,該線程會自動釋放對該同步監(jiān)視器的鎖定線程同步同步監(jiān)視器的目的阻止兩個線程對同一個共享資源進行并發(fā)訪問,因此通常推薦使用可能被并發(fā)訪問的共享資源充當同步監(jiān)視器,對于上面的示例我們應當使用賬戶(account)作為同步監(jiān)視器。上面的Demo中,我們把run()方法體內(nèi)的所有代碼者改成如下形式public

void

run(){synchronized(account){...//原來在run中的方法體}}見/geminno/thread3/Account.java/geminno/thread3/DrawThread.java/geminno/thread3/DrawTest.java線程同步同步方法與同步代碼塊對應,Java的多線程安全支持還提供了同步方法,同步

方法就是使用synchronized關鍵字來修飾某個方法,則該方法稱為同步方法。對于同步方法而言,無須顯式指定同步監(jiān)視器,同方法的同步監(jiān)視器是this,也就是對象本身需要說明的是我們不能在run()方法之前加上synchronized,因為我們的取錢或存錢是兩個不同的線程所以在同步的方法應當在Account類中實現(xiàn),我們可以在Account類中新建兩個方法,一個是存錢,一個是取錢的方法,我們把這兩個方法進行同步使用同步方法可以非常方便地實現(xiàn)線程安全類線程同步線程安全類具有特征1.該類的對象可以被多個線程安全地訪問2.每個線程調(diào)用該對象的任意方法之后都將得到正確的結(jié)果

3.每個線程調(diào)用該對象的任意方法后,該對象狀態(tài)依然保持合理狀態(tài)見/geminno/thread4/Account.java/geminno/thread4/DrawThread.java/geminno/thread4/DrawTest.java線程同步釋放同步監(jiān)視器的鎖定線程進入同步代碼塊,必須獲得對同步監(jiān)視器的鎖定,那么何時會釋放同步監(jiān)視器呢?線程不能顯式釋放同步監(jiān)視器,幾種釋放同步監(jiān)視器情況同步代碼塊執(zhí)行結(jié)束同步方法中遇到break

return終止了代碼塊同步代碼塊中出現(xiàn)Error或Exception執(zhí)行同步代碼塊時,程序執(zhí)行了同步監(jiān)視器的wait()方法,當前線程暫停下面的情況不會釋放同步監(jiān)視器的鎖定執(zhí)行同步方法或同步代碼塊時,程序調(diào)用sleep()

yield()來暫停當前線程線程執(zhí)行同步代碼塊時,其他線程調(diào)用了該線程的suspend()方法,將該線程掛起注意:我們應當盡量避免使用suspend()和resume()方法控制線程線程同步同步鎖(Lock)

Java5后提供了更為強大的線程同步機制--通過顯式定義同步鎖來實現(xiàn)同步同步鎖使用Lock對象來實現(xiàn)同步鎖有兩個根接口,一個是Lock,另一個ReadWriteLockLock的實現(xiàn)類是ReentrantLock(可重入鎖)(一般使用這個鎖)

ReadWriteLock的實現(xiàn)類是ReentrantReadWriteLock(可讀寫重入鎖)見/geminno/thread5/Account.java/geminno/thread5/DrawThread.java/geminno/thread5/DrawTest.java線程通信傳統(tǒng)的線程通信兩個線程一個代表取錢者,一個代表存錢者特殊的要求:系統(tǒng)要求存錢者和取錢者不斷重復存錢、取錢動作,而且要求每當存錢者將錢存入指定賬戶后,取錢者立即取出該筆錢。不允許存錢者連續(xù)兩次存錢,也不允許取錢者連續(xù)兩次取錢為了實現(xiàn)上面的特殊要求,可以借助Object類提供的wait()、notify()和notifyAll()三個方法,這三個方法不屬于Thread類,而是屬于Object類。但這三個方法必須由同步監(jiān)視器對象來調(diào)用,可以分成以下兩中情況:對于使用synchronized修飾的同步方法,因為該類的默認實例(this)就是同步監(jiān)視器,所以可以在同步方法中直接調(diào)用這3個方法對于使用synchronized修飾的同步代碼塊,同步監(jiān)視器是synchronized后括號里的對象,所以必須使用該對象調(diào)用這3個方法線程通信3個方法的解釋wait():導致當前線程等待,直到其也線程調(diào)用該同步監(jiān)視器的notify()或notifyAll()來喚醒。notify():喚醒在此同步監(jiān)視器上等待的單個線程。如果有多個線程在此監(jiān)視器上等待,則會選擇其中一個進行喚醒,選擇哪個線程是任意的。notifyAll():喚醒在此同步監(jiān)視器上等待的所有線程線程通信上面的要求中我們可以用一個標志來表示該賬戶是否有存款??存款者:1.當標志為false時,表示沒有存款,存款者線程可以向賬戶中存款,存款后將標志設為true,并調(diào)用notify()或notfiyAll()方法來喚醒其他線程;2.如果標志是true,就調(diào)用wait()讓當前線程等待取款者:

1.當標志為true時,表示有存款,取款者線程可以直接從賬戶中取款,取款后將標志設為false,并調(diào)用notify()或notfiyAll()方法來喚醒其他線程;2.如果標志為false,就調(diào)用wait()讓當前線程等待見/geminno/thread6/Account.java/geminno/thread6/DrawThread.java/geminno/thread6/DepositThread.java/geminno/thread6/DrawTest.java線程通信使用Condition控制線程通信如果不使用synhronized關鍵字來保證同步,而是直接使用Lock對象來保證同步,則系統(tǒng)中就不存在隱式的同步監(jiān)視器,也就不能使用wait()notify()notifyAll()方法進行線程通信使用Lock對象來同步時,Java提供了Condition類來保持協(xié)調(diào),使用

Condition可以讓那些已經(jīng)得到Lock對象卻無法繼續(xù)執(zhí)行的線程釋放Lock對象,Condition也可喚醒其他處于等待的線程Condition將同步監(jiān)視器方法(wait()notify()notifyAll())分解成不同的對象,以便通過將這些對象與Lock對象組合使用Lock替代了同步方法或同步代碼塊

Condition替代了同步監(jiān)視器的功能線程通信使用Condition控制線程通信

Condition實例被綁定在一個Lock對象上。要獲得特定Lock實例的

Condition實例,調(diào)用Lock對象的newCondition()方法就可以了。Condition提供的3個方法見/geminno/thread7/Account.java/geminno/thread7/DrawThread.java/geminno/thread7/DepositThread.java/geminno/thread7/DrawTest.java方法說明await()導致當前線程等待,直到其他線程調(diào)用該Condition的signal()方法或signalAll()方法來喚醒該線程signal()類似于notify()signalAll()類似于notifyAll()線程池啟動一個線程的代價是比較高的,因為涉及到與操作系統(tǒng)交互,使用線程池可以很好地提高性能線程池在系統(tǒng)啟動時就創(chuàng)建大量空閑的線程,程序?qū)⒁粋€Runnable

對象或Callable對象傳給線程池,線程池就會啟動一個線程來執(zhí)行它的run()或call()方法,當run()或call()方法執(zhí)行結(jié)束后,該線程并不會死亡,而是再次返回線程池中成為空閑狀態(tài),等待執(zhí)行下一個Runnable對象的run()或call()方法使用線程池可以有效地控制系統(tǒng)中并發(fā)線程數(shù)量,保證系統(tǒng)的性能Java5實現(xiàn)的線程池Java5之前,開發(fā)者必須手動實現(xiàn)線程池,從Java5開始,Java內(nèi)建支持線程池Java5新增了一個Executors工廠類來產(chǎn)生線程池線程池Java5用線程池來執(zhí)行線程任務的步驟

1.調(diào)用Executors類的靜態(tài)方法newFixedThreadPool(intThreadCount)來創(chuàng)建一個ExecutorService對象,這個對象代表一個線程池

2.創(chuàng)建Runnable實現(xiàn)類或Callable實現(xiàn)類的實例或Thread類的子類實例,作為線程執(zhí)行任務

3.調(diào)用ExecutorService對象的submit()方法來提交線程實例到線程池4.線程池會自動調(diào)用其中的空閑線程來執(zhí)行run()或call()方法

5.當不想提交任何任務時,調(diào)用ExecutorService對象的

shutdown()方法來關閉線程池見/geminno/thread8/ThreadPoolTest.java線程池Java7新增的ForkJoinPool ForkJoinPool(拆分結(jié)合池)

它可充分發(fā)揮多核cpu的性能ForkJoinPool可以支持將一個任務拆分成多個"小任務"并行計算,再把多個"小任務"的結(jié)果合并成總的計算結(jié)果ForkJoinPool是ExecutorService的實現(xiàn)類,因此是一種特殊的線程池ForkJoinPool的構造器方法說明ForkJoinPool(int

parallelism)創(chuàng)建一個包含parallelism個并行線程的ForkJoinPoolForkJoinPool()以Runtime.getRuntime().availableProcessors()方法的返回值作為parallelism參數(shù)來創(chuàng)建ForkJoinPool線程池Java7新增的ForkJoinPool??

創(chuàng)建了ForkJoinPool實例后,就可以調(diào)用ForkJoinPool的submint(ForkJoinTask

task)或invoke(ForkJoinTask

task)方法來執(zhí)行指定任務。

ForkJoinTask代表一個可以并行、合并的任務,它是一個抽象類,它還有兩個抽象子類:RecursiveAction:沒有返回值

2.RecursiveTask:有返回值見/geminno/thread8/ForkJoinPoolTest.java(無返回值)見/geminno/thread8/Sum.java(有返回值)線程相關類ThreadLocal類ThreadLocal,是Thread

Local

Variable(線程局部變量)為每一個使用該變量的線程提供一個變量值副本每個線程可獨立地改變自己副本,不會與其他線程沖突支持泛型ThreadLocal類使用很簡單,提供了三個public方法見/geminno/thread8/ThreadLocalTest.java方法說明T

get()返回此線程局部變量中當前線程副本中的值void

remove()刪除此線程局部變量中當前線程的值void

set(Tvalue)設置線程局部變量中當前線程副本中的值線程相關類ThreadLocal類說明ThreadLocal從另一個角度來解決多線程的并發(fā)訪問,ThreadLocal將需要并發(fā)訪問的資源復制出多份來,每個線程擁有一份資源,每一個線程都擁有自己的資源副本,從而也就沒有必要對該變量進行同步ThreadLocal并不能替代同步機制,兩者面向的問題領域不同同步機制是為了同步多個線程對相同資源的并發(fā)訪問,是多個線程之間進行通信的有效方式ThreadLocal是隔離多個線程的數(shù)據(jù)共享,從根本上避免了多個線程之間共享資源,從而也就不需要對多個線程進行同步如果需要進行多個線程之間共享資源,以達到線程之間通信功能,就使用同步機制,如果僅僅需要隔離多個線程之間的共享沖突,可以使用

ThreadLocal線程相關類包裝線程不安全的集合前面的集合中講到的ArrayList

LinkedList

HashSet

TreeSet

HashMapTreeM

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論