1. 程式人生 > >Java——實現Java多執行緒的三種方法

Java——實現Java多執行緒的三種方法

Java虛擬機器允許應用程式併發地執行多個執行緒。在Java語言中,多執行緒的實現一般有以下3種方法,其中前兩種是最常用的方法。

1.繼承Thread類,重寫run()方法

Thread本質上也是實現了Runnable介面的一個例項,它代表一個執行緒的例項。並且,啟動執行緒的唯一方法就是通過Thread類的start()方法。

start()方法是一個native(本地)方法,它將啟動一個新執行緒,並執行run()方法(Thread中提供的run()方法是一個空方法)。這種方式通過自定義直接extend Thread,並重寫run()方法,就可以啟動新執行緒並執行自己定義的run()方法,需要注意的是,呼叫start()方法後不是立即執行多執行緒程式碼,而是使得該賢臣變為可執行態(Runnable),什麼時候執行多執行緒程式碼是由作業系統決定的。

Thread的使用方法:

class MyThread extends thread{//建立執行緒
    public void run(){
        System.out.println("Thread body");//執行緒的函式體
    }
}

public class Test{
    public static void main(String args[])
    {
        MyThread thread=new Mythread();
        thread.start();//開啟執行緒
    }
}

2.實現Runnable介面,並實現該介面的run()方法

如要步驟如下:

  • 自定義類並實現Runnable介面,實現run()方法。
  • 建立Thread物件,用事先Runnable介面的物件作為引數例項化該Thread物件。
  • 呼叫Thread的start()方法。

示例如下:

class MyThread implements Runnable {//建立執行緒類
    public void run(){
        System.out.println("Thread body");//執行緒的函式體
    }
}

public class Test{
    public static void main(String args[])
    {
        MyThread thread=new Mythread();
        Thread t=new Thread(thread);
        t.start();//開啟執行緒
    }
}

從第一種方法和第二種方法的示例來看,我們可以發現,不管是通過繼承Thread類還是通過使用Runnable介面來實現多執行緒的方法,最終都還是通過Thread的物件的API來控制執行緒的。

 

引申:是否可以同時繼承Thread與實現Runnable介面?

當然可以啦。瞧本帥博主給你一個示例,你就知道啦~

public class Test extends Thread implements Runnable{
	public static void main(String args[])
	{
		Thread t=new Thread(new Test());
		t.start();	
	}
}

有些讀者看了這個例子,可能會懷疑這段程式沒有辦法編譯通過。因為從上面的例子中,我們可以看出,Test類實現了Runnable介面,但是並沒有實現介面的run()方法,可能有些讀者會認為這會導致編譯錯誤,但實際上它是能夠編譯通過並執行的,因為Test類從Thread類中即成了run()方法,這個繼承的 run()方法可以被當做對Runnable介面的實現,因此這段程式碼能夠編譯通過

那要是不想用從Thread類中繼承的方法,那該怎麼辦呢?好說,在Test類中重寫run()方法來實現Runnable介面中的run()方法就可以了,且看下面的示例:

public class Test extends Thread implements Runnable{
	public void run() {
		System.out.println("this is run()");
	}
	public static void main(String args[])
	{
		Thread t=new Thread(new Test());
		t.start();	
	}
}

 

3.實現Callable介面,重寫call()方法

Callable介面實際上是屬於Exector框架中的功能類,Callable介面與Runnable介面的功能類似,但是提供了比Runnable更強大的功能,主要表現為以下三點:

  • Callable可以在任務結束後提供一個返回值,Runnable無法提供這個功能。
  • Callable中的call()方法可以丟擲異常,而Runnable的run()方法不可以丟擲異常。
  • 執行Callable可以拿到一個Future物件,Future物件表示非同步計算的結果,它提供了檢查計算是否完成的方法。由於執行緒屬於非同步計算模型,因此無法從別的執行緒中得到函式的返回值。在這種情況下,就可以使用Future來監視目標執行緒呼叫call()方法的情況。當呼叫Future的get()方法以獲取結果的時候,當前執行緒就會阻塞,直到call()方法結束返回結果。

示例如下:

package javatest;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class CallableAndFuture {
	//建立執行緒類
	public static class CallableTest implements Callable<String>
	{
		@Override
		public String call() throws Exception {
			// TODO Auto-generated method stub
			return "Hello World";
		}
	}
		
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		ExecutorService threadPool=Executors.newSingleThreadExecutor();
		Future<String>future=threadPool.submit(new CallableTest());
		try {
			System.out.println("waiting thread to finish");
			System.out.println(future.get());
		}catch(Exception e){
			e.printStackTrace();
		}
	}
}

執行結果如下:

4.總結

以上三種方式中,前兩種方式執行緒執行完之後都沒有返回值,只有最後一種是帶返回值的。當要實現多執行緒時,一般推薦實現Runnable介面的方式,其原因是:

  • 首先,Thread類定義了多種方法可以被派生類使用或者重寫。但是隻有run()方法是必須被重寫的,在run()方法中實現了這個縣城的主要功能。這當然是實現Runnable介面所需的方法。
  • 其次,很多Java開發人員認為,一個類僅在它們需要被加強或者修改時才會被繼承。因此,如果沒有必要重寫Thread累的其他方法,那麼通過繼承Thread的實現方式與實現Runnable介面的效果相同,在這種情況下,最好通過實現Runnable介面的方式來建立執行緒。

 

好啦,以上就是實現Java多執行緒的三種方法的相關總結,如果大家有什麼更具體的發現或者發現文中有描述錯誤的地方,歡迎留言評論,我們一起學習呀~~

 

Biu~~~~~~~~~~~~~~~~~~~~宫å´éªé¾ç«è¡¨æå|é¾ç«gifå¾è¡¨æåä¸è½½å¾ç~~~~~~~~~~~~~~~~~~~~~~pia!