国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 編程 > Java > 正文

Java中的多線程

2019-11-06 07:01:18
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

前言

  昨晚在看死鎖相關(guān)的東西,看到了synchronized關(guān)鍵字,然后就想寫(xiě)一篇關(guān)于synchronized關(guān)鍵字的博客,就去仔細(xì)看了看相關(guān)的東西。synchronized關(guān)鍵字在使用多線程的時(shí)候使用,于是復(fù)習(xí)一下多線程的東西,寫(xiě)篇博客加深一下印象。   java中實(shí)現(xiàn)多線程的方式有兩種,一是繼承Thread類(lèi),二是實(shí)現(xiàn)Runnable接口,先看繼承Thread類(lèi)。

繼承Thread類(lèi)

  Threadjava.lang包中的一個(gè)類(lèi),實(shí)現(xiàn)了Runnable接口,Runnable接口源碼如下,簡(jiǎn)單粗暴。

public interface Runnable { /** * When an object implementing interface <code>Runnable</code> is used * to create a thread, starting the thread causes the object's * <code>run</code> method to be called in that separately executing * thread. * <p> * The general contract of the method <code>run</code> is that it may * take any action whatsoever. * * @see java.lang.Thread#run() */ public abstract void run();}

  ClassExtendsThread類(lèi),繼承了Thread類(lèi),在run方法中依次遞減打印出10到1。

public class ClassExtendsThread extends Thread { PRivate int num = 10; @Override public void run() { for (int i = 0 ; i < 10 ; i++) { if (num > 0) { // 打印出當(dāng)前線程名字和num當(dāng)前的值 System.out.println(currentThread().getName() + "--->" + num--); } } }}

  main函數(shù)代碼如下:

public class DemoTest { public static void main(String[] args) { ClassExtendsThread thread1 = new ClassExtendsThread(); ClassExtendsThread thread2 = new ClassExtendsThread(); thread1.start(); thread2.start(); }}

  運(yùn)行結(jié)果如下:

Thread-0--->10Thread-1--->10Thread-0--->9Thread-1--->9Thread-0--->8Thread-1--->8Thread-0--->7Thread-1--->7Thread-0--->6Thread-1--->6Thread-0--->5Thread-0--->4Thread-1--->5Thread-0--->3Thread-0--->2Thread-1--->4Thread-0--->1Thread-1--->3Thread-1--->2Thread-1--->1

  從結(jié)果中可以看出,兩個(gè)線程都啟動(dòng)起來(lái),并且交叉運(yùn)行,但是這兩個(gè)線程可以認(rèn)為他們是不關(guān)聯(lián)的,因?yàn)榫€程1和線程2各自擁有了新的num變量,即這兩個(gè)線程不共享該變量。接下來(lái)看實(shí)現(xiàn)Runnable接口的多線程Demo。

實(shí)現(xiàn)Runnable接口

  上面已經(jīng)看了Runnable接口的源碼,直接上Demo。

public class ClassImplRunnable implements Runnable { private int num = 10; @Override public void run() { for (int i = 0; i < 10; i++) { if (num > 0) { // 因?yàn)镽unnable中沒(méi)有currentThread方法,所以要加上Thread System.out.println(Thread.currentThread().getName() + "--->" + num--); } } }}

  ClassImplRunnableClassExtendsThread代碼幾乎一樣,不同的是實(shí)現(xiàn)了Runnable接口。測(cè)試代碼如下:

public class DemoTest { public static void main(String[] args) { ClassImplRunnable classImplRunnable = new ClassImplRunnable(); new Thread(classImplRunnable).start(); new Thread(classImplRunnable).start(); }}

  這里的ClassImplRunnable只實(shí)現(xiàn)了Runnable接口,但是沒(méi)有start方法,無(wú)法啟動(dòng)線程,但是Thread類(lèi)中有個(gè)構(gòu)造方法:

public Thread(Runnable target) { init(null, target, "Thread-" + nextThreadNum(), 0); }

傳入一個(gè)實(shí)現(xiàn)Runnable接口的類(lèi)即可創(chuàng)建一個(gè)新的線程,然后調(diào)用start方法即可啟動(dòng)線程。注意啟動(dòng)線程只能用start方法,如果調(diào)用run方法,那么就只是執(zhí)行了一個(gè)方法,并沒(méi)有啟動(dòng)線程。   運(yùn)行結(jié)果如下:

Thread-0--->10Thread-0--->8Thread-0--->7Thread-1--->9Thread-0--->6Thread-1--->5Thread-1--->3Thread-1--->2Thread-0--->4Thread-1--->1

  兩個(gè)線程交叉運(yùn)行,因?yàn)闆](méi)有使用同步鎖。同時(shí),這里兩個(gè)線程使用了同一個(gè)對(duì)象構(gòu)造了Thread,所以其實(shí)兩個(gè)線程運(yùn)行的時(shí)候共享了num變量。   仔細(xì)回顧一下兩次運(yùn)行,發(fā)現(xiàn)繼承Thread類(lèi)的ClassExtendsThread類(lèi)運(yùn)行時(shí),是直接創(chuàng)建了兩個(gè)ClassExtendsThread對(duì)象,但是ClassImplRunnable類(lèi)是創(chuàng)建了一個(gè)對(duì)象,但是創(chuàng)建了兩個(gè)Thread對(duì)象并啟動(dòng)線程,那么就不能說(shuō)繼承Thread的類(lèi)實(shí)現(xiàn)多線程不能共享資源,實(shí)現(xiàn)了Runnable接口的多線程才能共享資源。   接下里來(lái)模仿一下ClassImplRunnable類(lèi)啟動(dòng)線程的方式,代碼如下:

public class DemoTest { public static void main(String[] args) { ClassExtendsThread classExtendsThread = new ClassExtendsThread(); new Thread(classExtendsThread).start(); new Thread(classExtendsThread).start(); }}

  運(yùn)行結(jié)果如下:

Thread-2--->10Thread-1--->9Thread-1--->7Thread-1--->6Thread-1--->5Thread-1--->4Thread-1--->3Thread-1--->2Thread-1--->1Thread-2--->8

  結(jié)果可以看出,其實(shí)是共享了資源(num)的。   這里線程名字變了,因?yàn)閚ew了一個(gè)ClassExtendsThread對(duì)象的時(shí)候,就已經(jīng)創(chuàng)建了一個(gè)線程,而后面調(diào)用Thread的構(gòu)造函數(shù)又創(chuàng)建了兩個(gè)線程,而且只啟動(dòng)了線程2和3,即Thread-1Thread-2。   今天下午查了一下午資料,也沒(méi)有一個(gè)講的清楚的好文章,最后靈光一閃,用Google搜了一下,結(jié)果直接搜出來(lái)兩篇講的很好的文章,一個(gè)是GitHub的,一個(gè)是博客園的,按道理說(shuō)百度和必應(yīng)都能搜出來(lái)的,但是。。。

總結(jié)

  用ThreadRunnable都可以實(shí)現(xiàn)多線程,但是一般情況下還是用實(shí)現(xiàn)Runnable接口的方法來(lái)實(shí)現(xiàn)多線程,原因有以下幾點(diǎn):   1. 因?yàn)镴ava的單繼承特性,如果繼承Thread的話(huà)就不能再繼承其他類(lèi),而接口是可以實(shí)現(xiàn)多個(gè)的,所以實(shí)現(xiàn)Runnable接口更加靈活;   2. 關(guān)于很多文章提到的資源共享問(wèn)題,繼承了Thread類(lèi)的類(lèi)的對(duì)象,已經(jīng)是一個(gè)線程了,是可以直接調(diào)用start方法來(lái)啟動(dòng)線程的,但是如果要實(shí)現(xiàn)類(lèi)似于ClassImplRunnable這樣的所謂的“資源共享”,還需要把對(duì)象傳入Thread的構(gòu)造函數(shù)重新實(shí)例化Thread對(duì)象,比較麻煩,所以還是用實(shí)現(xiàn)Runnable接口的方法便捷一點(diǎn)。


發(fā)表評(píng)論 共有條評(píng)論
用戶(hù)名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 安陆市| 松潘县| 乃东县| 蒙自县| 柘城县| 晋中市| 钦州市| 平度市| 牟定县| 平陆县| 拉萨市| 焦作市| 班玛县| 建昌县| 翁源县| 龙游县| 宜昌市| 长海县| 南阳市| 洪泽县| 鄄城县| 罗江县| 平南县| 阿尔山市| 噶尔县| 项城市| 望奎县| 宾阳县| 三原县| 舒城县| 乌鲁木齐县| 拜泉县| 松阳县| 六安市| 崇仁县| 昆山市| 清丰县| 奉贤区| 万山特区| 章丘市| 土默特右旗|