java建立執行緒implement runnable 和 extends thread 比較
我們都知道java實現執行緒有兩種方法
一。繼承Thread類
二。實現Runnable介面
看到很多說法他們之間有一個區別是:實現Runnable接口才能實現資源共享。繼承thread的方式不行
並且附有類似以下的例項:
//Implement Runnable 的方式來實現執行緒classImplementsRunnableimplementsRunnable{privateint counter =0;publicvoid run(){
counter++;System.out.println("ImplementsRunnable : Counter : "+ counter); }}//通過繼承 Thread 類的方式classExtendsThreadextendsThread{privateint counter =0;publicvoid run(){
counter++;System.out.println("ExtendsThread : Counter : "+ counter);}}publicclassThreadVsRunnable{publicstaticvoid main(String args[])throwsException{// 多執行緒共享同一個變數(rc)ImplementsRunnable rc =newImplementsRunnable ();Thread t1 =newThread(rc);
t1.start();Thread.sleep(1000);//啟動下一個執行緒前,等待一秒鐘Thread t2 =newThread(rc);
t2.start();Thread.sleep(1000);//啟動下一個執行緒前,等待一秒鐘Thread t3 =newThread(rc);
t3.start();// 通過extend Thread只能為每一個執行緒建立新的物件ExtendsThread tc1 =newExtendsThread();
tc1.start();Thread.sleep(1000);ExtendsThread tc2 =newExtendsThread();
tc2.start();Thread.sleep(1000);ExtendsThread tc3 =newExtendsThread();
tc3.start();}}
輸出結果如下:
ImplementsRunnable:Counter:1ImplementsRunnable:Counter:2ImplementsRunnable:Counter:3ExtendsThread:Counter:1ExtendsThread:Counter:1ExtendsThread:Counter:1
他們通過這個例子得出:實現Runnable接口才能實現資源共享。繼承thread的方式不行 這個結論
其實我們仔細看一下這個例子,就會發現這個結論是錯的:
1.首先我們看一下通過 Implements Runnable 方式建立執行緒時,發生了什麼
擷取上面例子中的兩行程式碼:
ImplementsRunnable rc = new ImplementsRunnable();
Thread t1 = new Thread(rc);
rc物件是一個Runnable類,把它作為引數通過new Thread(Runnable arg)初始化了一個Thread。
我們進入Thread類的原始碼看一下(經過簡化,要檢視完整方法,參看java原始碼):
當new Thread的時候,會呼叫Thread的init()方法,初始化這個執行緒
/**
* 初始化一個Thread
* .......
* @引數 target :這個target引數的run()方法將會被最後呼叫(the object whose run() method gets called)
* ........
*/
private void init(...,Runnable target,....) {
......
this.target = target;
......
}
我們看到這個函式的關鍵是用傳遞給他的引數初始化這個Thread,註釋中明確說道呼叫Thread的start()方法時,最終會呼叫的是這個target引數的run方法,當這個Thread呼叫start()方法後,最終會呼叫到如下run()方法:
public void run() {
if (target != null) {
target.run();
}
}
我們可以看到正如前面init()方法的註釋所描述的一樣,最終會呼叫的是線程init()時傳遞給這個Thread的target引數的run方法。
所以正如一開始的例子中的程式碼那樣,用同一個Runnable target初始化多個執行緒,那麼這多個執行緒都會呼叫同一個target的run()方
法。至始至終這個ImplementsRunnable物件就只有一個。
在這裡要加一段話 雖然這樣實現了資源的共享,但是並沒有實現資源的同步,如下例子,我加入一個條件,如果counter小於10才能繼續+1(比如多個視窗同時賣火車票的場景):
class ImplementsRunnable implements Runnable {
private int counter = 0;
public void run() {
while(counter<10){
counter++;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
System.out.println(Thread.currentThread().getName()+":"+ counter);
}
}
}
public static void main(String args[]) throws Exception {
// Multiple threads share the same object.
ImplementsRunnable rc = new ImplementsRunnable();
Thread t1 = new Thread(rc);
t1.start();
Thread.sleep(1000); // Waiting for 1 second before starting next thread
Thread t2 = new Thread(rc);
t2.start();
Thread.sleep(1000); // Waiting for 1 second before starting next thread
Thread t3 = new Thread(rc);
t3.start();
}
執行結果如下,出現了同步錯誤:
Thread-5:2
Thread-6:3
Thread-5:4
Thread-5:6
Thread-6:7
Thread-7:8
Thread-5:9
Thread-6:10
Thread-7:9
Thread-5:10
如果我們要實現同步的話,就需要加入synchronized方式了(當然還可以通過原子操作的方式通過CAS無鎖實現)
修改後的程式碼如下:
class ImplementsRunnable implements Runnable {
private int counter = 0;
public void run() {
while(counter<10){
synchronized(this){
if(counter<10){
counter++;
System.out.println(Thread.currentThread().getName()+":"+ counter);
}
}
}
}
}
執行結果如下,達到了我們的目的:
Thread-5:1
Thread-6:2
Thread-7:3
Thread-7:4
Thread-6:5
Thread-6:6
Thread-6:7
Thread-6:8
Thread-6:9
Thread-5:10
那我們在看看通過extend Thread 的方式。它並沒有一個共同的Runnable物件來初始化3個Thread物件。每一個Thread都擁有自己一個獨立的Runnable物件。
當然不能實現資源的共享,因為現在每個Thread都有一個自己counter物件了。
那麼問題來了:難道用extends Thread的方式就不能實現共享嗎,答案是肯定可以實現:
方法有很多。我自己試著寫了一個:
package test;
public class TestThread {
public static void main(String args[]) throws Exception {
ExtendsThread tc1 = new ExtendsThread();
tc1.start();
ExtendsThread tc2 = new ExtendsThread();
tc2.start();
ExtendsThread tc3 = new ExtendsThread();
tc3.start();
}
}
class ExtendsThread extends Thread {
public void run() {
while(Resource.getCounter()<10){
Resource.count();
}
}
}
多加入了一個類Resource.javapackage test;
public class Resource {
private static int counter = 0;
public static int getCounter(){
return counter;
}
public static synchronized void count(){
if(counter<10){
counter++;
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+":"+counter);
}
}
}
執行結果如下:
Thread-5:1
Thread-5:2
Thread-6:3
Thread-5:4
Thread-7:5
Thread-6:6
Thread-7:7
Thread-6:8
Thread-7:9
Thread-6:10
可以看到 在這段程式碼中 我counter設定成了static,相應的用了class級別的鎖。
不過相比implement runnable的方式還是麻煩了很多。
所以從上面兩個比較我們可以得出
實現Runnable介面相比繼承Thread類有如下好處:
->避免單點繼承的侷限,一個類可以繼承多個介面。
->適合於資源的共享
相關推薦
java建立執行緒implement runnable 和 extends thread 比較
我們都知道java實現執行緒有兩種方法 一。繼承Thread類 二。實現Runnable介面 看到很多說法他們之間有一個區別是:實現Runnable接口才能實現資源共享。繼承thread的方式不行 並且附有類似以下的例項: //Implement Runnable 的方
JAVA多執行緒之Runnable和Thread比較
在我們開發的過程中常常會碰到多執行緒的問題,對於多執行緒的實現方式主要有兩種:實現Runnable介面、繼承Thread類。對於這兩種多執行緒的實現方式也是有著一些差異。既然實現了多執行緒那必然離不開管理這些執行緒,當問題比簡單時一個或者幾個執行緒就OK了,也涉
java 使用匿名內部類的方式建立執行緒並設定和獲取執行緒名字
有些方法需要傳入介面的例項或者抽象類的例項物件,比如Thread有一個構造方法,Thread(Runnable target) 這時可以可以自定義類實現Runnable介面,重寫介面中的方法,將自定義類的物件傳入構造方法中 也可以使用匿名內部類,即在建立Thread物件時傳入Runnable
-1-5 java 多執行緒 概念 程序 執行緒區別聯絡 java建立執行緒方式 執行緒組 執行緒池概念 執行緒安全 同步 同步程式碼塊 Lock鎖 sleep()和wait()方法的區別 為什麼wait(),notify(),notifyAll()等方法都定義在O
本文關鍵詞: java 多執行緒 概念 程序 執行緒區別聯絡 java建立執行緒方式 執行緒組 執行緒池概念 執行緒安全 同步 同步程式碼塊 Lock鎖 sleep()和wait()方法的區別 為什麼wait(),notify(),notifyAll()等方法都定義在Object類中 多執行緒
併發程式設計學習總結(一) :java 建立執行緒的三種方式的優缺點和例項
java 建立執行緒有三種方式: (一) 實現Runnable介面 優點:(1) 建立執行緒的同時可以繼承其他的類,從而可以擴充套件類的功能。
Java建立執行緒的方法
轉載自:https://www.cnblogs.com/3s540/p/7172146.html Java使用Thread類代表執行緒,所有的執行緒物件都必須是Thread類或其子類的例項。Java可以用三種方式來建立執行緒,如下所示: 1)繼承Thread類建立執行緒 2)實現Runn
jvm之java建立執行緒導致記憶體異常
1。以下執行緒啟動,請注意儲存當前工作,因為jav的執行緒是對映到作業系統的核心執行緒上,下面程式碼執行,容易導致作業系統假死 會導致部署程式碼的缺失,執行以上程式會導致如下結果如: 請強制結束以下程序。 分析如下: java的執行緒執行是對映到作業系統的核心執行緒上的。
Java多執行緒-44-靜態和非靜態方法同步鎖物件是什麼
前面一篇,我們知道了synchronized關鍵字擴起來範圍的程式碼塊就可以實現同步,其實,在Java中,只需要在方法上加上synchronized關鍵字即可,就像加上static一樣。本篇來看看加上synchronized關鍵字修飾的非靜態和靜態方法的同步鎖物件是什麼。 1.非靜態同步鎖物
java建立執行緒的四種方法(轉)
java中建立執行緒的四種方法以及區別 Java使用Thread類代表執行緒,所有的執行緒物件都必須是Thread類或其子類的例項。Java可以用四種方式來建立執行緒,如下所示: 1)繼承Thread類建立執行緒 2)實現Runnable介面建立執行緒 3)使用Callable和Future建立執行緒
Java多執行緒學習---Condition和wait、notify(十三)
1.問題:實現兩個執行緒交叉執行(Condition和wait、notify都可以實現) public class ConditionStudy { public static void main(String[] args) { //執行緒程式碼 BussinessTes
java 建立執行緒的三種方法
在java中使用Thread類代表執行緒,所有的執行緒物件都必須是Thread類或其子類的例項,建立執行緒有三種方式: 1.通過繼承Thread類建立執行緒; 2.通過實現Runnable介面建立執行緒; 3.通過使用Callable和Future建立執行緒。 建立執行緒demo
JAVA 多執行緒(生產者和消費者模式)
在生產-消費模式中:通常由兩類執行緒,即若干個生產者的執行緒和若干個消費者的執行緒。生產者執行緒負責提交使用者請求,消費者執行緒則負責具體處理生產者提交的任務,在生產者和消費者之間通過共享記憶體快取區進行通訊。 主要構成: provider:生產者執行緒負責生產資料 consume
java:多執行緒(獲取名字和設定名字)
* 1.獲取名字 * 通過getName()方法獲取執行緒物件的名字 * 2.設定名字 * 通過建構函式可以傳入String型別的名字 package com.heima.threadmethod; p
java:多執行緒(實現Runnable的原理)及二種方式的區別
* 1,看Thread類的建構函式,傳遞了Runnable介面的引用 * 2,通過init()方法找到傳遞的target給成員變數的target賦值 * 3,檢視run方法,發現run方法中有判斷,如果target不為null就會呼叫Runnable介面子類物件的run方法 *
JAVA 建立執行緒ThreadDemo類
class Thread1 extends Thread{ public void run(){ //獲取當前執行緒名字 System.out.println(Thread.currentThread().getName()); } } class Thread2 extends
java 多執行緒 死鎖和valitile關鍵字
死鎖 兩個或者多個執行緒都在等待對方釋放鎖,在寫多執行緒程式碼時要注意避免這種死鎖的發生 發生死鎖後可以在dos命令列輸入jps命令檢視java程序狀況 可以試用jstack -l 程序號 命令檢視當前類的問題 關閉jvm停止死鎖 以上節
Java多執行緒之interrupt()和執行緒終止方式
1. interrupt()說明 在介紹終止執行緒的方式之前,有必要先對interrupt()進行了解。 關於interrupt(),java的djk文件描述如下:http://docs.oracle.com/javase/7/docs/api/ Interrupts this thread
Java建立執行緒的三種方式
繼承Thread (1)定義Thread類的子類,重寫該類的run方法,該run方法的方法體就代表了執行緒要完成的任務。因此把run()方法稱為執行體。 (2)建立Thread子類的例項,即建立了執行緒物件。 (3)呼叫執行緒物件的start()方法來啟動該執行緒。
java多執行緒之ReentrantLock和 Condition
ReentrantLock 是JDK中內建鎖,也稱可重入鎖,API也較為簡單。 Condition 可實現 執行緒間通訊,由ReentrantLock 例項產生即 lock.new Condition(); 下面這個demo模擬最簡單的生產者 消費者模式,Add執行緒模
Java建立執行緒的三種方式以及優劣對比
Java使用Thread類代表執行緒,所有的執行緒物件都必須是Thread類或者其子類例項。每個執行緒的作用是完成一定的任務,實際上是執行一段程式流 #1. 繼承Thread類建立執行緒類 通過繼承Thread類來建立並啟動多執行緒的步驟如下: 定