Java并发编程(6):Runnable和Thread实现多线程的区别(含代码)
Java中實(shí)現(xiàn)多線(xiàn)程有兩種方法:繼承Thread類(lèi)、實(shí)現(xiàn)Runnable接口,在程序開(kāi)發(fā)中只要是多線(xiàn)程,肯定永遠(yuǎn)以實(shí)現(xiàn)Runnable接口為主,因?yàn)閷?shí)現(xiàn)Runnable接口相比繼承Thread類(lèi)有如下優(yōu)勢(shì):
1、可以避免由于Java的單繼承特性而帶來(lái)的局限;
2、增強(qiáng)程序的健壯性,代碼能夠被多個(gè)線(xiàn)程共享,代碼與數(shù)據(jù)是獨(dú)立的;
3、適合多個(gè)相同程序代碼的線(xiàn)程區(qū)處理同一資源的情況。
下面以典型的買(mǎi)票程序(基本都是以這個(gè)為例子)為例,來(lái)說(shuō)明二者的區(qū)別。
首先通過(guò)繼承Thread類(lèi)實(shí)現(xiàn),代碼如下:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | class MyThread extends Thread{ ????private int ticket = 5; ????public void run(){ ????????for (int i=0;i<10;i++) ????????{ ????????????if(ticket > 0){ ????????????????System.out.println("ticket = " + ticket--); ????????????} ????????} ????} } public class ThreadDemo{ ????public static void main(String[] args){ ????????new MyThread().start(); ????????new MyThread().start(); ????????new MyThread().start(); ????} } |
某次的執(zhí)行結(jié)果如下:
從結(jié)果中可以看出,每個(gè)線(xiàn)程單獨(dú)賣(mài)了5張票,即獨(dú)立地完成了買(mǎi)票的任務(wù),但實(shí)際應(yīng)用中,比如火車(chē)站售票,需要多個(gè)線(xiàn)程去共同完成任務(wù),在本例中,即多個(gè)線(xiàn)程共同買(mǎi)5張票。
下面是通過(guò)實(shí)現(xiàn)Runnable接口實(shí)現(xiàn)的多線(xiàn)程程序,代碼如下:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | class MyThread implements Runnable{ ????private int ticket = 5; ????public void run(){ ????????for (int i=0;i<10;i++) ????????{ ????????????if(ticket > 0){ ????????????????System.out.println("ticket = " + ticket--); ????????????} ????????} ????} } public class RunnableDemo{ ????public static void main(String[] args){ ????????MyThread my = new MyThread(); ????????new Thread(my).start(); ????????new Thread(my).start(); ????????new Thread(my).start(); ????} } |
某次的執(zhí)行結(jié)果如下:
從結(jié)果中可以看出,三個(gè)線(xiàn)程一共賣(mài)了5張票,即它們共同完成了買(mǎi)票的任務(wù),實(shí)現(xiàn)了資源的共享。
針對(duì)以上代碼補(bǔ)充三點(diǎn):
1、在第二種方法(Runnable)中,ticket輸出的順序并不是54321,這是因?yàn)榫€(xiàn)程執(zhí)行的時(shí)機(jī)難以預(yù)測(cè),ticket–并不是原子操作。
2、在第一種方法中,我們new了3個(gè)Thread對(duì)象,即三個(gè)線(xiàn)程分別執(zhí)行三個(gè)對(duì)象中的代碼,因此便是三個(gè)線(xiàn)程去獨(dú)立地完成賣(mài)票的任務(wù);而在第二種方法中,我們同樣也new了3個(gè)Thread對(duì)象,但只有一個(gè)Runnable對(duì)象,3個(gè)Thread對(duì)象共享這個(gè)Runnable對(duì)象中的代碼,因此,便會(huì)出現(xiàn)3個(gè)線(xiàn)程共同完成賣(mài)票任務(wù)的結(jié)果。如果我們new出3個(gè)Runnable對(duì)象,作為參數(shù)分別傳入3個(gè)Thread對(duì)象中,那么3個(gè)線(xiàn)程便會(huì)獨(dú)立執(zhí)行各自Runnable對(duì)象中的代碼,即3個(gè)線(xiàn)程各自賣(mài)5張票。
3、在第二種方法中,由于3個(gè)Thread對(duì)象共同執(zhí)行一個(gè)Runnable對(duì)象中的代碼,因此可能會(huì)造成線(xiàn)程的不安全,比如可能ticket會(huì)輸出-1(如果我們System.out….語(yǔ)句前加上線(xiàn)程休眠操作,該情況將很有可能出現(xiàn)),這種情況的出現(xiàn)是由于,一個(gè)線(xiàn)程在判斷ticket為1>0后,還沒(méi)有來(lái)得及減1,另一個(gè)線(xiàn)程已經(jīng)將ticket減1,變?yōu)榱?,那么接下來(lái)之前的線(xiàn)程再將ticket減1,便得到了-1。這就需要加入同步操作(即互斥鎖),確保同一時(shí)刻只有一個(gè)線(xiàn)程在執(zhí)行每次for循環(huán)中的操作。而在第一種方法中,并不需要加入同步操作,因?yàn)槊總€(gè)線(xiàn)程執(zhí)行自己Thread對(duì)象中的代碼,不存在多個(gè)線(xiàn)程共同執(zhí)行同一個(gè)方法的情況。
from:?http://www.importnew.com/20584.html
原文出處:?蘭亭風(fēng)雨
總結(jié)
以上是生活随笔為你收集整理的Java并发编程(6):Runnable和Thread实现多线程的区别(含代码)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Java并发编程(5):volatile
- 下一篇: Java并发编程(7):使用synchr