1. 程式人生 > >與執行緒的再次邂逅——建立執行緒

與執行緒的再次邂逅——建立執行緒

以前在學習執行緒時只用過一種建立方式,由於面試常問,現在來熟悉下建立執行緒的三種方式(其實是有四種,這裡只介紹3種)。

一.繼承Thread類

1.首先線上程實現類中繼承Thread類,使執行緒實現類成為Thread的子類。然後重寫Thread類中的run方法,run方法實際上就是執行體,方法中的程式碼實現就是執行緒所要完成的任務。

2.建立子類的物件,實際上也就是建立了Thread類的物件。

3.通過物件呼叫Thread類中的run方法,啟動執行緒。

//繼承Thread
public class Demo extends Thread{
	//執行體
		public void run(){
			//重寫run方法		
			System.out.println("執行重寫之後的run方法");
		}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//建立並啟動執行緒
       Demo demo=new Demo();
       demo.start();
	}
}

二.繼承Runnable介面

1.在介面實現類中繼承Runnable介面,重寫Runnable介面中的run方法,這時的run方法也是執行體。

2.建立Runnable實現類的例項物件,這時的物件並不是真正的執行緒物件,所以要把這時的物件傳給Thread來建立物件,這時的Thread物件才是真正的執行緒物件。

3.通過Thread物件呼叫run方法啟動執行緒。

//繼承Runnable介面
public class Demo1 implements Runnable{
	//重寫介面中的run方法
	public void run(){
		System.out.println("執行重寫之後的run方法");
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//建立實現介面類的物件
		Demo1 demo1=new Demo1();
		//建立Thread的物件,並分配新的Thread物件
		Thread thread=new Thread(demo1);
		//呼叫Thread裡面的start方法啟動執行緒
		thread.start();
	}
}

三.繼承callable介面和利用Future介面實現

這種實現方式與前兩種相比,執行體發生了改變,但顯得比前兩種更為強大,該方式的執行體為Callable介面中的call方法,此方法可以有返回值,並且可以利用Future介面中的get方法接收執行緒結束之後的返回值,並且Future介面有一實現類Futuretask,這個實現類既繼承了Future介面,又繼承了Runnable介面,因此該類的物件可以作為Thread物件的target來建立Thread物件.(下面以返回值型別為int型為例)

1.在介面實現類中繼承Callable介面,重寫介面中的call方法,這時call方法才是執行緒的執行體,並且有返回值。

2.建立介面實現類的物件,並且將該物件傳遞給Futuretask類來建立Futuretask物件,再講Futuretask物件傳遞給Thread來建立Thread物件。

3.用Thread物件呼叫start方法啟動執行緒。

4.線上程結束之後,利用Futuretask物件呼叫get方法得到call方法的返回值(get方法需要丟擲異常)。

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

//使用Callable和Future實現
public class Demo2 implements Callable<Integer>{
	public static void main(String[] args) throws InterruptedException, ExecutionException{
		//例項化介面實現類的物件
		Demo2 demo2=new Demo2();
		//建立FutureTask物件封裝Demo2物件
		FutureTask<Integer> future=new FutureTask<>(demo2);
		//建立Thread類的物件封裝FutureTask物件
		Thread thread =new Thread(future);
		//啟動執行緒(呼叫了重寫之後的call方法)
		thread.start();
		//獲得call方法的返回值
		int c=future.get();
		System.out.println("c= "+c);
	}
	@Override
	//執行體
	public Integer call() throws Exception {
		// TODO Auto-generated method stub
		System.out.println("呼叫了重寫之後的call方法");
		int a=3;
		return a;
	}
}

小結:

1.三種方式相比,不太建議使用第一種,因為java中是隻能繼承單個類的(除Object外),如果繼承了Thread類就無法繼承其他的類,所以就顯得這種方式比較笨拙。而介面是可以多繼承的,所以建議一般使用繼承介面來實現執行緒。

2.實現Runnable和Callable方式基本相同,但不同的是二者的執行體,後者的執行體有返回值。