Java中Runnable和Thread的區別

来源:http://www.cnblogs.com/sjm19910902/archive/2017/02/14/6396117.html
-Advertisement-
Play Games

在java中可有兩種方式實現多線程,一種是繼承Thread類,一種是實現Runnable介面;Thread類是在java.lang包中定義的。一個類只要繼承了Thread類同時覆寫了本類中的run()方法就可以實現多線程操作了,但是一個類只能繼承一個父類,這是此方法的局限。 下麵看例子: 但是,此時 ...


在java中可有兩種方式實現多線程,一種是繼承Thread類,一種是實現Runnable介面;Thread類是在java.lang包中定義的。一個類只要繼承了Thread類同時覆寫了本類中的run()方法就可以實現多線程操作了,但是一個類只能繼承一個父類,這是此方法的局限。

下麵看例子:

package org.thread.demo;  
class MyThread extends Thread{  
private String name;  
public MyThread(String name) {  
super();  
this.name = name;  
}  
public void run(){  
for(int i=0;i<10;i++){  
System.out.println("線程開始:"+this.name+",i="+i);  
}  
}  
}  
package org.thread.demo;  
public class ThreadDemo01 {  
public static void main(String[] args) {  
MyThread mt1=new MyThread("線程a");  
MyThread mt2=new MyThread("線程b");  
mt1.run();  
mt2.run();  
}  
} 

  但是,此時結果很有規律,先第一個對象執行,然後第二個對象執行,並沒有相互運行。在JDK的文檔中可以發現,一旦調用start()方法,則會通過JVM找到run()方法。下麵啟動start()方法啟動線程:

package org.thread.demo;  
public class ThreadDemo01 {  
public static void main(String[] args) {  
MyThread mt1=new MyThread("線程a");  
MyThread mt2=new MyThread("線程b");  
mt1.start();  
mt2.start();  
}  
}; 

  

這樣程式可以正常完成互動式運行。那麼為啥非要使用start();方法啟動多線程呢?

在JDK的安裝路徑下,src.zip是全部的java源程式,通過此代碼找到Thread中的start()方法的定義,可以發現此方法中使用了private native void start0();其中native關鍵字表示可以調用操作系統的底層函數,那麼這樣的技術成為JNI技術(java Native Interface).

Runnable介面

在實際開發中一個多線程的操作很少使用Thread類,而是通過Runnable介面完成。

public interface Runnable{  
public void run();  
} 

例子:

package org.runnable.demo;  
class MyThread implements Runnable{  
private String name;  
public MyThread(String name) {  
this.name = name;  
}
public void run(){  
for(int i=0;i<100;i++){  
System.out.println("線程開始:"+this.name+",i="+i);  
}  
}  
}; 

  但是在使用Runnable定義的子類中沒有start()方法,只有Thread類中才有。此時觀察Thread類,有一個構造方法:public Thread(Runnable targer)此構造方法接受Runnable的子類實例,也就是說可以通過Thread類來啟動Runnable實現的多線程。(start()可以協調系統的資源):

package org.runnable.demo;  
import org.runnable.demo.MyThread;  
public class ThreadDemo01 {  
public static void main(String[] args) {  
MyThread mt1=new MyThread("線程a");  
MyThread mt2=new MyThread("線程b");  
new Thread(mt1).start();  
new Thread(mt2).start();  
}  
} 

  

兩種實現方式的區別和聯繫:

在程式開發中只要是多線程肯定永遠以實現Runnable介面為主,因為實現Runnable介面相比繼承Thread類有如下好處:

  • 避免點繼承的局限,一個類可以繼承多個介面。
  • 適合於資源的共用

以賣票程式為例,通過Thread類完成:

package org.demo.dff;  
class MyThread extends Thread{  
private int ticket=10;  
public void run(){  
for(int i=0;i<20;i++){  
if(this.ticket>0){  
System.out.println("賣票:ticket"+this.ticket--);  
}  
}  
}  
}; 

  下麵通過三個線程對象,同時賣票:

package org.demo.dff;  
public class ThreadTicket {  
public static void main(String[] args) {  
MyThread mt1=new MyThread();  
MyThread mt2=new MyThread();  
MyThread mt3=new MyThread();  
mt1.start();//每個線程都各賣了10張,共賣了30張票  
mt2.start();//但實際只有10張票,每個線程都賣自己的票  
mt3.start();//沒有達到資源共用  
}  
} 

如果用Runnable就可以實現資源共用,下麵看例子:

package org.demo.runnable;  
class MyThread implements Runnable{  
private int ticket=10;  
public void run(){  
for(int i=0;i<20;i++){  
if(this.ticket>0){  
System.out.println("賣票:ticket"+this.ticket--);  
}  
}  
}  
}  
package org.demo.runnable;  
public class RunnableTicket {  
public static void main(String[] args) {  
MyThread mt=new MyThread();  
new Thread(mt).start();//同一個mt,但是在Thread中就不可以,如果用同一  
new Thread(mt).start();//個實例化對象mt,就會出現異常  
new Thread(mt).start();  
}  
}; 

雖然現在程式中有三個線程,但是一共賣了10張票,也就是說使用Runnable實現多線程可以達到資源共用目的。

Runnable介面和Thread之間的聯繫:

public class Thread extends Object implements Runnable

發現Thread類也是Runnable介面的子類。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • c#中的類是最常見的實際上就是對某種類型的對象定義變數和方法的原型。 結構是值類型,而類是引用類型。 1.與類不同,結構的實例化可以不使用 new 運算符。結構可以聲明構造函數,但它們必須帶參數。 2.一個結構不能從另一個結構或類繼承,而且不能作為一個類的基。所有結構都直接繼承自 System.Va ...
  • 假如需要實現一個代碼編輯器,其中一個很重要的功能是實現代碼提示,類似VS的代碼智能提示。下麵用Roslyn編譯器來實現一個簡單的代碼提示功能。 代碼提示,首先必須需要知道對象的類型信息,然後通過迭代獲取成員。 ...
  • 系統環境: vmware安裝的centos6.7虛擬機 jdk1.8版本 maven庫3.3.9版本(在使用源碼編譯啟動的時候需要修改配置文件與當前使用的maven版本匹配,最低使用版本好像是3.1.5,記不清了) 其他的一些ssh工具隨意。 1、二進位工程 ①NIFI下載地址:http://nif ...
  • 靜態成員:靜態類中的成員加入static修飾符,即是靜態成員.可以直接使用類名+靜態成員名訪問此靜態成員,因為靜態成員存在於記憶體,非靜態成員需要實例化才會分配記憶體,所以靜態成員不能訪問非靜態的成員..因為靜態成員存在於記憶體,所以非靜態成員可以直接訪問類中靜態的成員. 1、靜態全局變數 定義:在全局變 ...
  • (慕課網視頻學習--C++離港篇的學習memo)1: 函數的參數預設值,只能在最右邊。 如果有三個參數,只有中間一個有預設值,這是錯誤的。 函數聲明的時候寫預設值,定義的時候不要寫。(有些編譯器會出錯。)2:內聯函數:編譯時,將函數體實參和代碼替換掉調用語句。 關聯字 inline 內聯函數是建議性 ...
  • 1.普通成員普通成員都是屬於對象的用對象調用 2.靜態成員靜態成員是屬於類的用類名調用 stactic 靜態關鍵字 靜態方法裡面不能包含普通成員普通方法裡面可以包含靜態成員 抽象類: 1.關鍵字:abstract2.抽象類可以包含抽象方法和普通方法3.abstract關鍵字可以定義方法為抽象方法,抽 ...
  • Hibernate工作原理及為什麼要用? 原理:1.通過Configuration().configure();讀取並解析hibernate.cfg.xml配置文件2.由hibernate.cfg.xml中的<mapping resource="com/xx/User.hbm.xml"/>讀取並解析 ...
  • #include #include using namespace std; void main() { string s="Hello Lucy!"; //s.replace(5,1,"Lily"); //"Lucy" -> "Lily" int indexStart=s.find("Lucy")... ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...