【java】【多執行緒】建立執行緒的兩種常用方式(2)

love_Aym發表於2018-04-15

java虛擬機器允許應用程式吧併發的執行多個執行緒。

Java有三種建立執行緒的方式,分別是繼承Thread類、實現Runable介面和使用執行緒池。前兩種最常用。最後一種後期補充學習。


1、繼承Thread類

(1)定義類整合Thread類,並重寫父類的run()方法,方法裡的內容就是執行緒所要執行的任務; 
(2)建立子類的例項,即生成執行緒的例項物件; 

(3)呼叫現成的start()方法來啟動執行緒,內部會自動呼叫run方法。

注意:若不使用start()方法開啟執行緒,只呼叫run方法相當於單純的呼叫方法而已並沒有開啟執行緒,程式依然會使用main單執行緒執行。

    start方法有兩種含義:

  • 啟動多執行緒。
  • 呼叫執行緒中的run方法(具體怎麼呼叫run方法是由虛擬機器執行的,無法通過原始碼檢視)
public class Demo2_Thread {	
        public static void main(String[] args) {
	MyThread mt = new MyThread();			//4,建立自定義類的物件
	mt.start();					//5,開啟執行緒
					
	for(int i = 0; i < 3000; i++) {
		System.out.println("bb");
		}
	}
			
	}
	class MyThread extends Thread {			//1,定義類繼承Thread
	    public void run() {				//2,重寫run方法
		for(int i = 0; i < 3000; i++) {		//3,將要執行的程式碼,寫在run方法中
			System.out.println("aa");
		}
	}
}

2、實現Runnable介面

(1)定義類實現Runnable介面

(2)實現run方法,這個run()方法和Thread中的run()方法一樣是執行緒的執行體。把新執行緒要做的事寫在run方法中

    注意:Runnable介面中只有run方法

(3)建立自定義的Runnable的子類物件

(4)建立Thread物件, 傳入Runnable子類物件。因為runnable介面中沒有start方法,需借用Thread類的start方法。Thread物件才是真正的執行緒物件

(5)呼叫start()開啟新執行緒, 內部會自動呼叫Runnable的run()方法.

public class Demo3_Runnable {
	public static void main(String[] args) {
		MyRunnable mr = new MyRunnable();		//4,建立自定義類物件
		//Runnable target = new MyRunnable();           
		Thread t = new Thread(mr);			//5,將其當作引數傳遞給Thread的建構函式
		t.start();					//6,開啟執行緒
					
		for(int i = 0; i < 3000; i++) {
			System.out.println("bb");
			}
		}
	}
	
		class MyRunnable implements Runnable {	        //1,自定義類實現Runnable介面
		        @Override
		        public void run() {											//2,重寫run方法
			for(int i = 0; i < 3000; i++) {		//3,將要執行的程式碼,寫在run方法中
				System.out.println("aaaaaaaaaaaaaaaaaaaaaaaaaaaa");
			}
		}
				
	}

實現Runnable的原理  (瞭解)

* 檢視原始碼

    * 1,看Thread類的建構函式,傳遞 了Runnable介面的引用

    * 2,通過init()方法找到傳遞的target給成員變數的target賦值

    * 3,檢視run方法,發現run方法中有判斷,如果target不為null就會呼叫Runnable介面子類物件的run方法


3、繼承方式與實現方式有什麼區別

1、檢視原始碼的區別:

  • 繼承Thread:由於子類重寫了Thread類的run(), 當呼叫start()時, 直接找子類的run()方法
  • 實現Runnable:建構函式中傳入了Runnable的引用, 成員變數記住了它(this), start()呼叫run()方法時內部判斷成員變數Runnable的引用是否為空, 不為空編譯時看的是Runnable的run(),執行時執行的是子類的run()方法

2、多執行緒執行程式碼位置不同:
    繼承Thread類:程式碼存放在Thread類的run方法中

    實現Runnable類:程式碼存放在Runnable介面的run方法中。


4、繼承方式與實現方式的優缺點

1、 繼承Thread

    * 好處:可以直接使用Thread類中的方法,程式碼簡單

    * 弊端:如果已經有了父類,就不能用這種方法

2、 實現Runnable介面

    * 好處:即使自己定義的執行緒類有了父類也沒關係,因為有了父類也可以實現介面,而且介面是可以多實現的,避免了單繼承的侷限性

    * 弊端:不能直接使用Thread中的方法需要先獲取到執行緒物件後,才能得到Thread的方法,程式碼複雜


注意:繼承方式和實現方式的優缺點是互換的。


5、使用匿名內部類實現執行緒的兩種方式

1)繼承Thread類

    new Thread() {				    //1,new 類(){}繼承這個類
	public void run() {			    //2,重寫run方法
		for(int i = 0; i < 3000; i++) {	    //3,將要執行的程式碼,寫在run方法中
			System.out.println("aa");
			}
		}
	}.start();

2)實現Runnable介面

new Thread(new Runnable(){	                    //1,new 介面(){}實現這個介面
	public void run() {			    //2,重寫run方法
		for(int i = 0; i < 3000; i++) {	    //3,將要執行的程式碼,寫在run方法中
			System.out.println("bb");
			}
		}
	}).start(); 






 

相關文章