java线程的简单例子(Thread and runnable)
生活随笔
收集整理的這篇文章主要介紹了
java线程的简单例子(Thread and runnable)
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
http://interper56-sohu-com.iteye.com/blog/172303
其實(shí)要了解java多線程只需要理解以下幾個(gè)事情:1) java.lang.Thraed類
2) java.lang.Runnable接口
3) synchronized關(guān)鍵字
4) wait(),.notify(), notifyAll();
That’s all.
[java.util.Thread類]
Jdk的線程實(shí)現(xiàn)類,只要繼承這個(gè)類那么我們就可以實(shí)現(xiàn)自己的線程。
如果你想要繼承這個(gè)類,主要需要重載run方法。
例如:
Java代碼 ?
當(dāng)你要是用它的時(shí)候
Java代碼 ?
當(dāng)你運(yùn)行這個(gè)方法的時(shí)候,就會(huì)打出Hello world.
[java.lang.Runnable接口]
因?yàn)槔^承Thread類就無(wú)法繼承別的你想要變?yōu)榫€程的類,
所以java.lang.Runnable接口可以實(shí)現(xiàn)你的愿望
那么看下面的例子:
食物類:
Java代碼 ?
消費(fèi)者類:
Java代碼 ?
消費(fèi)者線程類:
Java代碼 ?
生產(chǎn)者類:
Java代碼 ?
消費(fèi)者類:
Java代碼 ?
測(cè)試類:
Java代碼 ?
上面代碼主要模擬了生產(chǎn)者和消費(fèi)者生產(chǎn)食物,消費(fèi)食物的過(guò)程,
這里面先讓生產(chǎn)者生產(chǎn)了1個(gè)食物,然后讓消費(fèi)者消費(fèi)了1個(gè)食物。
主要是想說(shuō)明我們自己實(shí)現(xiàn)的Runnable接口的類必須借助Thread類
才可以把它變成一個(gè)線程,如果不借助Thread類,即使我們實(shí)現(xiàn)了run()方法,
這個(gè)類的對(duì)象也不會(huì)是一個(gè)線程。
說(shuō)白了,就是用Thread(Runnable thread)這個(gè)構(gòu)造方法把我們實(shí)現(xiàn)的Runnable
街口的類傳入,然后通過(guò)Thread的start方法,來(lái)調(diào)用我們的run方法,其實(shí)
我們實(shí)現(xiàn)的Runnable接口的類要想變?yōu)榫€程,是要通過(guò)Thread這個(gè)載體來(lái)實(shí)現(xiàn)。
但是上面的實(shí)現(xiàn)存在一個(gè)問(wèn)題,我們并不能保證同一時(shí)間內(nèi)只有一個(gè)
CustomerThread線程在消費(fèi),不能保證在同一時(shí)間只有一個(gè)ProductorThread
線程在生產(chǎn)。
所以我們引入了synchronized關(guān)鍵字
[synchronized關(guān)鍵字]
通過(guò)在CustomerThraed的consume方法和ProductorThread的increase
方法前面加入synchronized關(guān)鍵字就可以解決上面所說(shuō)的問(wèn)題。
改動(dòng)后的方法為:
Java代碼 ?
那么synchronized關(guān)鍵字到底是干什么用的呢?
就是進(jìn)入到synchronized關(guān)鍵字所包含的代碼塊的線程
都會(huì)嘗試獲得對(duì)象的鎖,等拿到對(duì)象的鎖后就可以進(jìn)去執(zhí)行代碼,
如果得不到,就在那里阻塞,等待其它線程釋放鎖,那么怎么用呢?
1)在方法前用synchronized關(guān)鍵字,如下:
Java代碼 ?
當(dāng)線程進(jìn)入到這個(gè)方法的時(shí)候,這個(gè)線程就會(huì)獲得這個(gè)方法所在對(duì)象的鎖,
那么其他的進(jìn)程想要進(jìn)入這個(gè)方法,首先嘗試去獲得這個(gè)方法所在對(duì)象的鎖,
但是已經(jīng)被前一個(gè)線程霸占了,所只能等待,當(dāng)前一個(gè)線程把這段代碼執(zhí)行
完畢,那么后來(lái)的線程就可以獲得這個(gè)對(duì)象鎖了,當(dāng)然它進(jìn)去后又會(huì)把后面的
線程阻塞在外面等待。
這種方法等同于:
Java代碼 ?
但是這種方法我們把整個(gè)對(duì)象都鎖住了,其他線程想要執(zhí)行這個(gè)類中的其它用
Synchronized方法聲明的方法都不可以了,因?yàn)橄胍M(jìn)入其它的synchronized
方法也要先獲得這個(gè)對(duì)象的鎖,所以這種方法比較霸道,我們不建議這么做,
所以出現(xiàn)了第二種方法。
2)聲明一個(gè)臨時(shí)的對(duì)象,讓進(jìn)入同一個(gè)方法的線程去獲得這個(gè)臨時(shí)對(duì)象的鎖,
? 那么獲得這個(gè)臨時(shí)對(duì)象的鎖,并不是整個(gè)對(duì)象的鎖,所以并不會(huì)鎖住整個(gè)對(duì)象,
? 當(dāng)然也就避免了上面第一種所遇到的問(wèn)題:
Java代碼 ?
Obj是一個(gè)臨時(shí)的對(duì)象,當(dāng)多個(gè)線程進(jìn)入到這個(gè)方法的時(shí)候都會(huì)嘗試去獲得這個(gè)
Obj對(duì)象的鎖,誰(shuí)先獲得,誰(shuí)就可以繼續(xù)執(zhí)行,否則阻塞在外面,等待前一個(gè)進(jìn)程
結(jié)束執(zhí)行synchronized內(nèi)的代碼,出了synchronized包含的代碼塊之后,
會(huì)馬上自動(dòng)釋放對(duì)這個(gè)obj對(duì)象的鎖。
[wait(), notify()和notifyAll()]
其實(shí)采用了上面的synchronized關(guān)鍵字之后,上面的代碼還是有問(wèn)題,
什么問(wèn)題?
我們?cè)賮?lái)仔細(xì)分析一下Synchronzied關(guān)鍵字,
Synchronzied關(guān)鍵字對(duì)線程來(lái)說(shuō)就是這么一回事:
1) 線程進(jìn)入synchronized代碼塊:嘗試獲得對(duì)象鎖
2) 線程出了synchronized代碼塊:釋放對(duì)象鎖
說(shuō)白了,就是誰(shuí)有鎖,誰(shuí)就可以繼續(xù)干活,沒(méi)有就得等。
加鎖就是限制同一時(shí)間有多個(gè)線程同時(shí)去訪問(wèn)公共的資源。
但是問(wèn)題也就來(lái)了,synchronized可以限制對(duì)公共的資源訪問(wèn),
但是無(wú)法決定線程訪問(wèn)公共資源的順序,所以引入了wait(),
Notify(), notifyAll 等原語(yǔ)來(lái)控制線程訪問(wèn)的順序。
注意這3個(gè)原語(yǔ)是當(dāng)前對(duì)象的方法,不是當(dāng)前線程的方法。
那么讓我們來(lái)看看這三個(gè)原語(yǔ)有什么用:
1) wait(): 使當(dāng)前線程阻塞,釋放它所獲得的對(duì)象的鎖
2) notify(): 通知虛擬機(jī)當(dāng)前線程準(zhǔn)備要釋放它所獲得的對(duì)象的鎖,
?????????????? 當(dāng)調(diào)用了wait()方法或者當(dāng)這個(gè)線程出了synchronized
?????????????? 代碼塊之后,這兩個(gè)動(dòng)作就是釋放了當(dāng)前線程對(duì)對(duì)象的鎖的持有,
?????????????? 那么其它的被阻塞的線程又可以執(zhí)行了。
3) notify(): 跟notify()沒(méi)有什么大區(qū)別,notify是通知1個(gè)被阻塞的線程做準(zhǔn)備,
?????????????? notifyAll()是通知所有被阻塞的線程做準(zhǔn)備,至于哪個(gè)線程可以獲得
?????????????? 這個(gè)鎖,那就看JVM的啦!
所以對(duì)于上面的生產(chǎn)者與消費(fèi)者的例子,
正確的流程是,
如果消費(fèi)者有東西可以消費(fèi),那么我們就讓他消費(fèi),
如果還需要生產(chǎn),還可以生產(chǎn),那么我們就讓生產(chǎn)者生產(chǎn),
只需要修改CustomerThread類ProductorThread類,
Food類 MainTest類。
那么我們的最終代碼如下:
CustomerThread類:
Java代碼 ?
ProductorThread類:
Java代碼 ?
Food類:
Java代碼 ?
MainTest類:
Java代碼 ?
終于寫完了,累死我了~~~
- 多線程問(wèn)題.rar (19.1 KB)
- 描述: 這篇文檔和對(duì)應(yīng)的源代碼
- 下載次數(shù): 35
?
總結(jié)
以上是生活随笔為你收集整理的java线程的简单例子(Thread and runnable)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Spring batch 2.0例子(l
- 下一篇: java.util.concurrent