一般使用線程有兩種方式:繼承Thread類重寫run方法;另一種就是實現Runnable接口,實現run方法。但是run方法沒有返回值,假如我們在使用線程的時候想要知道運行結果,就只能使用重寫run方法,並且使用回調來得到運行結果。但是我們Callable接口的call方法,可以返回執行結果。如下:
public interface Runnable
{
public abstract void run();
}
public interface Callable
{
public abstract Object call()
throws Exception;
}
Future: 表示異步計算的結果。它提供了檢查計算是否完成的方法,以等待計算的完成,並獲取計算的結果。計算完成後只能使用
get 方法來獲取結果,如有必要,計算完成前可以阻塞此方法。取消則由 cancel 方法來執行。還提供了其他方法,以確定任務是正常完成還是被取消了。一旦計算完成,就不能再取消計算。如果爲了可取消性而使用
Future 但又不提供可用的結果,則可以聲明 Future<?> 形式類型、並返回 null 作爲底層任務的結果。
public abstract boolean <code><strong><a target=_blank href="">cancel</a></strong>(boolean mayInterruptIfRunning)</code> ;
cancel用來取消任務,取消成功返回true,取消失敗返回false。mayInterruptIfRunning表示正在執行但還沒執行完的任務是否可以取消。如果任務已完成、或已取消。那麼不管mayInterruptIfRunning是ture還是false,方法執行返回false。如果任務在執行中,那麼若mayInterruptIfRunning爲ture那麼返回true;若mayInterruptIfRunning爲false,結果返回false。如果任務還沒執行,不管mayInterruptIfRunning是ture還是false,方法返回true。
public abstract Object get()
throws InterruptedException, ExecutionException;
get方法用來獲取線程執行返回結果。這個方法回阻塞,知道返回結果。 public abstract boolean isCancelled();
如果在任務正常完成前將其取消,則返回 true。get(long timeout, TimeUnit unit)
如有必要,最多等待爲使計算完成所給定的時間之後,獲取其結果(如果結果可用)。public abstract boolean isDone();
如果任務已完成,則返回 true。
FutureTask:可取消的異步計算。利用開始和取消計算的方法、查詢計算是否完成的方法和獲取計算結果的方法,此類提供了對
Future
的基本實現。僅在計算完成時才能獲取結果;如果計算尚未完成,則阻塞
get 方法。一旦計算完成,就不能再重新開始或取消計算。
Callable:Callable 接口類似於 Runnable,兩者都是爲那些其實例可能被另一個線程執行的類設計的。但是 Runnable 不會返回結果,並且無法拋出經過檢查的異常。 Callable
接口只有一個call方法,如下:
public abstract Object call()
throws Exception;
因爲Executor接口只提供了一個方法,參數中只能接受Runnable類型,如下:
public abstract void execute(Runnable runnable);
因此,Callable只能與ExecutorService一起使用。因爲ExecutorService提供了可接受Callable類型的參數。如下: public abstract Future submit(Callable callable);
public abstract Future submit(Runnable runnable, Object obj);
public abstract Future submit(Runnable runnable);
下面來看使用示例:
示例1:使用Callable和Future,並且輸出線程計算返回值
public class Test3 {
public static void main(String[] args) {
ExecutorService executor=Executors.newCachedThreadPool();
Future<Integer> future=executor.submit(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
int sum=0;
for (int i = 1; i <= 1000; i++) {
sum+=i;
}
return sum;
}
});
try {
System.out.println("線程執行結果:"+future.get());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
輸出結果:
線程執行結果:500500
示例2:使用Callable和FutureTask,並且輸出線程計算返回值
public class CallableFutureTask {
public static void main(String[] args) {
ExecutorService executor=Executors.newCachedThreadPool();
FutureTask<Integer> futureTask=new FutureTask<Integer>(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
int sum=0;
for (int i = 1; i <= 1000; i++) {
sum+=i;
}
return sum;
}
});
executor.submit(futureTask);
executor.shutdown();
try {
System.out.println("線程執行結果:"+futureTask.get());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
示例3:使用使用Callable和FutureTask,並且輸出線程計算返回值。用啓動普通線程來執行public class CallableFutureTaskThread {
public static void main(String[] args) {
FutureTask<Integer> futureTask=new FutureTask<Integer>(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
int sum=0;
for (int i = 1; i <= 1000; i++) {
sum+=i;
}
return sum;
}
});
Thread thread=new Thread(futureTask);
thread.start();
try {
System.out.println("線程執行結果:"+futureTask.get());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}