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