1. 程式人生 > >java建立執行緒implement runnable 和 extends thread 比較

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.java
package 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執行RunnableThread比較

在我們開發的過程中常常會碰到多執行緒的問題,對於多執行緒的實現方式主要有兩種:實現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執行學習---Conditionwait、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類來建立並啟動多執行緒的步驟如下: 定