生活随笔
收集整理的這篇文章主要介紹了
java线程的创建和启动深度解析
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
線程的創(chuàng)建和啟動
java使用Thread類代表線程,所有的線程對象都必須是Thread類或者其子類的實(shí)例。
java創(chuàng)建線程有三種方法:
一:繼承Thread類創(chuàng)建線程類
通過Thread類來創(chuàng)建并啟動多線程的步驟如下
定義Therad類的子類,并重寫該類的Thread方法,該run()方法體就代表了線程需要完成的任務(wù),因此把run()方法稱為線程執(zhí)行體;創(chuàng)建Thread子類的實(shí)例,即創(chuàng)建線程對象; 3) 調(diào)用線程的start()方法來啟動該線程;
start()方法的作用:啟動一個分支線程,在JVM中開辟一個新的空間,并執(zhí)行這個方法瞬間就結(jié)束了,這個方法的作用是為了開啟一個新棧空間,只要新的棧空間開發(fā)出來,start()方法就結(jié)束了,線程啟動成功,啟動成功的線程會自動調(diào)用run()方法,并且run()方法,在分支棧的棧底部,
public class createThread extends Thread{private int i;//重寫run()方法,run()方法體就是多線程執(zhí)行體public void run(){//這段程序運(yùn)行在分支棧中for (int j = 0; j < 100; j++) {System.out.println("分支棧——,》"+j+ getName());}}//這是mai'n方法,這里的代碼在主線程中運(yùn)行,屬于主線程public static void main(String[] args) {//新建一個分支線程對象createThread ct=new createThread();//啟動線程ct.start();//這里的代碼還是在主線程中運(yùn)行for (int i = 0; i < 1000; i++) {System.out.println(Thread.currentThread());}}
}
二:實(shí)現(xiàn)Runnable接口創(chuàng)建線程類
實(shí)現(xiàn)Runnable接口創(chuàng)建線程類的步驟如下:
定義Runnable接口的實(shí)現(xiàn)類,并重寫該接口中的run()方法,run()方法時該線程的執(zhí)行體。創(chuàng)建Runnable實(shí)現(xiàn)類的實(shí)例,并以此作為Thread的target構(gòu)造方法來創(chuàng)建Thread對象,該Thread方法才是真正的線程類。調(diào)用線程對象的start()方法來啟動線程
public class createRunnabe implements Runnable {public static void main(String[] args) {/* //創(chuàng)建一個可以運(yùn)行的對象;createRunnabe cr=new createRunnabe();//將可運(yùn)行的對象封裝成一個線程對象Thread thread=new Thread(cr);//啟動線程*/Thread thread=new Thread(new createRunnabe()); //合并代碼thread.start();for (int i = 0; i <100 ; i++) {System.out.println("主線程--》"+i);}}@Overridepublic void run() {for (int i = 0; i < 100; i++) {System.out.println("分支線程-->"+i);}}
}
注意:
Runnable對象僅僅作為Thread對象的Target,Runnable實(shí)現(xiàn)類里包含的run()方法僅僅作為線程的執(zhí)行體,而實(shí)際上線程對象依舊是Thread實(shí)例,所以該Thread線程負(fù)責(zé)執(zhí)行其target的run()方法。
三:使用接口Callable和接口Future創(chuàng)建線程
Callable接口提供了一個call()方法作為線程的執(zhí)行體,但是call()方法比run()方法功能更強(qiáng)大。
? Call方法有返回值;
? Call方法可以聲明拋出的異常;
因此可以提供一個Callable接口的實(shí)現(xiàn)類作為Thread的target,代替runnable接口的run()執(zhí)行體,但是Callable接口是java5的特性,不是Runnable接口的子接口,所以Callable接口不能直接作為Thread的target.
java5提供了Futuru接口來代表Callable接口里的Call()方法的返回值,并為Future接口提供了一個實(shí)現(xiàn)類FutureTask,該實(shí)現(xiàn)類實(shí)現(xiàn)了FutureTask實(shí)現(xiàn)了Future接口,并實(shí)現(xiàn)了Callable接口的實(shí)現(xiàn)類—可以作為Thread類的target.
創(chuàng)建并啟動有返回值的線程的步驟:
創(chuàng)建Callable接口的實(shí)現(xiàn)類,并實(shí)現(xiàn)Call()方法,該call()方法將作為線程執(zhí)行體,且該Call()方法有返回值,在創(chuàng)建Callable實(shí)現(xiàn)類的實(shí)例,這里使用匿名內(nèi)部類實(shí)現(xiàn)Callable接口,也可以使用Lambda表達(dá)式實(shí)現(xiàn)接口。(應(yīng)為Callable接口是函數(shù)式接口所以可以使用Lambda表達(dá)式來創(chuàng)建Callable對象)使用FutureTast類來包裝Callable對象,該FutureTusk對象封裝了Callable對象的Call()方法的返回值。使用FutureTask對象作為Thread對象的target創(chuàng)建并啟動新線程。
public class ThirdThread {public static void main(String[] args) {/*FutureTask(Callable<V> callable)創(chuàng)建一個 FutureTask會在運(yùn)行,執(zhí)行給定的 Callable。*///采用匿名內(nèi)部類來實(shí)現(xiàn)Callable接口中的call()方法FutureTask futuretask = new FutureTask(new Callable(){@Overridepublic Object call() throws Exception {for (int i = 0; i < 100; i++) {System.out.println(Thread.currentThread().getName() + " :" + i);}//call方法可以有返回值return this;}});Thread thread=new Thread(futuretask);//啟動分支此線程,實(shí)質(zhì)上是以Callable接口來創(chuàng)建并啟動線程thread.start();for (int i = 0; i < 100; i++) {System.out.println(Thread.currentThread().getName()+": "+i);}}
}
創(chuàng)建線程的三種方式對比
通過繼承Thread類,實(shí)現(xiàn)Runnable,實(shí)現(xiàn)Callable接口都可以實(shí)現(xiàn)多線程,不過實(shí)現(xiàn)Runnable接口和實(shí)現(xiàn)Callable接口的方式基本相同,只是Callable接口里定義的方法有返回值,可以聲明并拋出異常。因此這兩種實(shí)現(xiàn)接口的方式差不多:
實(shí)現(xiàn)接口的方式和繼承Thread類的主要差別:
優(yōu)勢:
? 線程實(shí)現(xiàn)了Callable、Runnable接口還可以繼承其他類,提高了程序的擴(kuò)展性。
? 實(shí)現(xiàn)接口的情況下,多個線程可以共享一個target對象非常適合于多個線程來處理同一份資源,從而可以將CPU代碼、數(shù)據(jù)分開,形成清晰的模型.
劣勢:
? 編程稍微復(fù)雜,如果需要訪問當(dāng)前線程,則必須使用Thread.CurrentThread()方法。
總結(jié)
以上是生活随笔為你收集整理的java线程的创建和启动深度解析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。