Java并发基础01. 传统线程技术中创建线程的两种方式
傳統(tǒng)的線程技術(shù)中有兩種創(chuàng)建線程的方式:一是繼承Thread類,并重寫run()方法;二是實(shí)現(xiàn)Runnable接口,覆蓋接口中的run()方法,并把Runnable接口的實(shí)現(xiàn)扔給Thread。這兩種方式大部分人可能都知道,但是為什么這樣玩就可以呢?下面我們來(lái)詳細(xì)分析一下這兩種方法的來(lái)龍去脈。
1. 揭秘Thread中run() |
上面我們看到這兩種方式都跟run()方法有關(guān),所以我們來(lái)看一下Thread的源碼中run()方法到底都干了什么: @Override public void run() {if (target != null) {target.run();} }
我們可以看出,run()方法中很簡(jiǎn)單,只有一個(gè)if語(yǔ)句,如果target不為空就執(zhí)行target的run()方法,否則什么也不干,那么這target到底是何方神圣呢?我們點(diǎn)擊進(jìn)去可以看到:
private Runnable target;原來(lái)target就是Runnable接口,我們?cè)冱c(diǎn)進(jìn)Runnable看看:
@FunctionalInterface public interface Runnable {public abstract void run(); }Runnable中就一個(gè)方法,也是run()方法!好了,現(xiàn)在再回到Thread類的run()方法中,如果target不為空,即實(shí)現(xiàn)了Runnable接口,也即實(shí)現(xiàn)了Runnable中的run()方法,那么我們就使用該接口中的run()方法;如果target為空,即沒有實(shí)現(xiàn)Runnable接口,那我們什么也不做,即線程創(chuàng)建后立馬就消失了。
所以到這里,大家就明白了為什么創(chuàng)建線程有上面兩種方式了。第一種:你不是要先進(jìn)行if判斷么?我現(xiàn)在不判斷了,我把你的if干掉,我在run()方法中自己寫代碼,想干啥就干啥,即重寫Thread中的run()方法,;第二種:你不是要先進(jìn)行if判斷么?行,給你一個(gè)Runnable接口讓你判斷,但你還是得調(diào)用我Runnable中的run()方法啊,那我重寫我Runnable中的run()方法不就行了!
知道了來(lái)龍去脈后,下面就針對(duì)這兩種傳統(tǒng)的方式寫個(gè)實(shí)例。
2. 創(chuàng)建方式1:繼承Thread類 |
只要兩步即可創(chuàng)建并開啟一個(gè)線程:
- 繼承Thread類,并實(shí)現(xiàn)run()方法;
- 調(diào)用start()方法開啟線程。
由于只要實(shí)現(xiàn)一個(gè)run()方法即可,所以我們可以使用java中的匿名內(nèi)部類來(lái)實(shí)現(xiàn),如下:
public class TraditionalThread {public static void main(String[] args) {/********** 第一種方法:繼承Thread類,覆寫run()方法 **************/Thread thread1 = new Thread(){@Overridepublic void run() {try {Thread.sleep(500);//讓線程休息500毫秒} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName());//打印出當(dāng)前線程名}};thread1.start();//開啟線程} }3. 創(chuàng)建方式2:實(shí)現(xiàn)Runnable接口 |
只要兩步即可創(chuàng)建并開啟一個(gè)線程:
- 實(shí)現(xiàn)Runnable接口,并實(shí)現(xiàn)run()方法;
- 調(diào)用start()方法開啟線程。
由于只要實(shí)現(xiàn)一個(gè)run()方法即可,所以我們也可以使用java中的匿名內(nèi)部類來(lái)實(shí)現(xiàn),如下:
public class TraditionalThread {public static void main(String[] args) {/********** 第二種方法:實(shí)現(xiàn)Runnable接口,扔給Thread **************/Thread thread2 = new Thread(new Runnable() {@Overridepublic void run() {try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName());}});thread2.start();} }4. 兩種方式同時(shí)使用 |
如果有個(gè)哥們比較給力,他兩種方式同時(shí)使用了,即:既實(shí)現(xiàn)了Thread類中的run()方法,又給Thread扔了一個(gè)實(shí)現(xiàn)了run()方法的Runnable。如下所示:
public class TraditionalThread {public static void main(String[] args) {//這哥們的代碼寫的比較給力new Thread(new Runnable() {@Overridepublic void run() {try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("Runnable:" + Thread.currentThread().getName());}}){@Overridepublic void run() {try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("Thread:" + Thread.currentThread().getName());}}.start();}}現(xiàn)在又會(huì)執(zhí)行哪個(gè)呢?我們運(yùn)行一下上面的程序就會(huì)發(fā)現(xiàn),它會(huì)打印出Thread的信息,所以運(yùn)行的是Thread的run()方法,知道結(jié)論了,但是為啥呢?
從面向?qū)ο蟮乃枷肴タ紤]:上面一段代碼其實(shí)是新new了一個(gè)對(duì)象(子對(duì)象)繼承了Thread對(duì)象(父對(duì)象),在子對(duì)象里重寫了父類的run()方法,父對(duì)象中扔了個(gè)Runnable進(jìn)去,父對(duì)象中的run()方法就是最初的帶有if判斷的run()方法。
好了,現(xiàn)在執(zhí)行start()后,肯定先在子類中找run()方法,找到了,父類的run()方法自然就被干掉了,所以會(huì)打印出Thread:,如果我們現(xiàn)在假設(shè)子類中沒有重寫run()方法,那么必然要去父類找run()方法,父類的run()方法中就得判斷是否有Runnable傳進(jìn)來(lái),現(xiàn)在有一個(gè),所以執(zhí)行Runnable中的run()方法,那么就會(huì)打印Runnable:出來(lái)。
OK,傳統(tǒng)的創(chuàng)建線程的兩種方式就總結(jié)這么多~如有錯(cuò)誤之處,歡迎留言指正~
轉(zhuǎn)載于:https://www.cnblogs.com/eson15/p/9822870.html
總結(jié)
以上是生活随笔為你收集整理的Java并发基础01. 传统线程技术中创建线程的两种方式的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Solr安装步骤 + dataimpor
- 下一篇: Tarjan有向图强连通分量