1. 程式人生 > >Java執行緒的基本使用(二)

Java執行緒的基本使用(二)

除了通過Runnable注入以及實現Thread類的run方法之外(其實都是Runnable),java還提供了Callable、Future和FutureTask這幾個與多執行緒相關的概念,不過這幾個型別都只能用於執行緒池中。

Callable宣告如下:

public interface Callable<V>{
	V call() throws Exception;
}

Callable感覺和Runnable非常相似,除了上面說的只能用於執行緒池,不同點在於Callable是一個泛型介面,允許返回一個泛型物件,同時支援丟擲異常。

public class ThreadDemo5 {

	public static void main(String[] args) {
		MyThread5<A> t1=new MyThread5<A>();
		ExecutorService pool=Executors.newSingleThreadExecutor();//建立單一執行緒池
		pool.submit(t1);
	}
	
}

abstract class BaseObject{
	String str;
}

class A extends BaseObject{
	public A(){
		str="This is A.";
	}
}

class MyThread5<T extends BaseObject> implements Callable<T>{

	@Override
	public T call() throws Exception {
		System.out.println("MyThread5的call方法執行");
		return (T) new A();
	}
	
}

執行之後,你會發現,輸出了“MyThread5的call方法執行”,但是,要如何獲取返回值呢?

我們發現,sumbit方法返回一個Future類的物件,Future類為執行緒池提供了一些類任務標準:cancle用於對執行結果的取消;isDone用於判斷是否完成;get用於獲取callable的返回值,set用於結果設定。所以,當我們需要獲取返回值的時候,直接利用get方法即可,注意使用get方法會直接阻塞執行緒,直到獲取到對應的結果:

main函式改寫為:
public static void main(String[] args) {
		MyThread5<A> t1=new MyThread5<A>();
		ExecutorService pool=Executors.newSingleThreadExecutor();//建立單一執行緒池
		Future future=pool.submit(t1);
		try {
			BaseObject a=(BaseObject)future.get();
			System.out.println("str="+a.str);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ExecutionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
}

結果輸出:

MyThread5的call方法執行
str=This is A.

事實上,Future只是一個抽象介面(public abstract interfacejava.util.concurrent.Future),真正實現的類是FutureTask<T>。FutureTask的宣告為

public class java.util.concurrent.FutureTask implements java.util.concurrent.RunnableFuture

,可以看出實現了RunnableFuture介面,而RunnableFuture又繼承了Runnable 、Future介面

public abstract interface java.util.concurrent.RunnableFuture extends java.lang.Runnable,java.util.concurrent.Future

故擁有它們兩者的特點,因此,FutureTask既可以和Runnable一樣,通過Thread封裝執行,也可以交給執行緒池來執行。

public class ThreadDemo6 {
	
	public static void main(String[] args) {
		FutureTask<String> ft=new FutureTask<String>(new Callable(){
			@Override
			public Object call() throws Exception {
				return "FutureTask 返回值";
			}
			
		});
		ExecutorService pool=Executors.newSingleThreadExecutor();
		pool.submit(ft);
		try {
			System.out.println(ft.get());
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ExecutionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

執行結果:

FutureTask 返回值