java多線程(六)
使用Runnable接口創建線程
Runnable接口
-
只有一個run()方法
-
Thread類實現了Runable接口
-
便於多個線程共享資源
-
Java不支持多繼承,如果已經繼承了某個基類,便要實現Runnable接口類生成多線程以實現Runnable的對象為參數建立新的線程
兩種線程構造方式的比較
- 使用Runnable接口
可以將cpu、代碼和數據分開,形成清晰的模型,還可以從其他類繼承
- 直接繼承Thread類
編寫簡單,直接繼承,重寫run方法,不能再從其他類繼承
實例
運行結果:
開啟線程
主線程結束
thread3準備休眠:1750
thread1準備休眠:1889
thread2準備休眠:186
thread2休眠結束
thread3休眠結束
thread1休眠結束
線程內部數據共享
用同一個實現了Runnable接口的對象作為參數創建多個線程,多個線程共享同一個對象中的相同的數據
運行結果:
開啟線程
結束線程
thread1準備休眠:2224
thread3準備休眠:2224
thread2準備休眠:2224
thread1休眠結束
thread2休眠結束
thread3休眠結束
說明:
因為是用同一個Runnable類型對象創建的3個新線程,這三個線程就共享了這個對象的私有成員sleepTime,在本次運行中,三個線程都休眠了2224毫秒
線程安全問題:
對於有一些應用,數據共享是不安全的 ,而且恰好應用中的某個類是單例的,那麽就不要把數據寫為成員變量,比如HttpServlet。
案例2:獨立且同時運行的線程有時需要共享一些數據並且考慮到彼此的狀態和動作.
-
用三個線程模擬三個售票口,總共出售20張票
-
用3個線程模仿3個售票口的售票行為
-
這3個線程應該共享20張票的數據
運行結果:
開始售票
售票口1號出售票號:20
.....
售票口3號出售票號:3
售票口3號出售票號:1
售票口1號出售票號:4
售票口1號結束
售票口3號結束
售票口2號出售票號:2
售票口2號結束
說明:
在這個例子中,創建了3個線程,每個線程調用的是同一個SellTickets對象中的run()方法,訪問的是同一個對象中的變量(tickets)
如果是通過創建Thread的子類來模擬售票過程,再創建3個線程,則每個線程都會有各自的方法和變量,雖然方法是相同的,但變量卻是各自有20張票,因而結果將會是各賣出20張票,和業務需求不符合了。
java多線程(六)