天天看點

Java中實作多線程關鍵詞整理

Java中的Runable,Callable,Future,FutureTask,ExecutorService,Excetor,Excutors,ThreadPoolExcetor在這裡對這些關鍵詞,以及它們的用法做一個總結。

首先将它們分個類:

Runable,Callable

Future,FutureTask

ExecutorService,Executor,Excutors,ThreadPoolExcetor

1. 關于Ranable和Callable

首先Java中建立線程的方法有三種:

  1. 繼承Thread類,覆寫run方法
  2. 實作Runable接口,實作run方法
  3. 實作Callable接口,實作run方法

三種實作的優缺點:

  1. 繼承Thread,單繼承的緣故,不能再繼承其他類,擷取目前線程this
  2. 實作Runable接口,沒有傳回值,擷取目前線程Thread.currentThread()
  3. 實作Callable接口,可通過Future.get()擷取傳回值,擷取目前線程 Thread.currentThread()

繼承Thread,兩個步驟:

class DemoThread extends Thread {    @Override
    public void run() {        super.run();        // Perform time-consuming operation...
    }
}DemoThread t = new DemoThread();
t.start();      
  • 繼承Thread類,覆寫run()方法。
  • 建立線程對象并用start()方法啟動線程。

實作Runable,一般使用如下:

new Thread(new Runnable() {    @Override
    public void run() {        // do something
    }
}).start();      

為了簡單。

以上兩種方式擷取線程執行的結果相當麻煩,不能直接擷取。JDK1.5增加了 Callable, Callable 的 call() 方法可以傳回值和抛出異常。Callable 可以傳回裝載有計算結果的 Future 對象。

Callable的源碼:

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

Callable的基本使用方法:

FutureTask<Integer> futureTask = new FutureTask<Integer>(new Callable<Integer>() {    @Override
    public Integer call() throws Exception {        // do something
        return null;
    }
});
Thread thread = new Thread(futureTask);
thread.start();
Integer result = futureTask.get();      

運作 Callable 任務可以拿到一個 Future 對象,通過Future的get()方法拿到線程執行的傳回值。那麼...Future,FutureTask差別是什麼,怎麼使用?

->next()

2. 關于Future和FutureTask

為了擷取線程的執行結果,引入了Future的FutureTask,那麼他們是什麼關系,如何使用?

Future類位于java.util.concurrent包下,它是一個接口:

public interface Future<V> {    boolean cancel(boolean mayInterruptIfRunning);    boolean isCancelled();    boolean isDone();    V get() throws InterruptedException, ExecutionException;    V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}      

Future 定義了5個方法:

  1. boolean cancel(boolean mayInterruptIfRunning):試圖取消對此任務的執行。如果任務已完成、或已取消,或者由于某些其他原因而無法取消,則此嘗試将失敗。當調用 cancel() 時,如果調用成功,而此任務尚未啟動,則此任務将永不運作。如果任務已經啟動,則 mayInterruptIfRunning 參數确定是否應該以試圖停止任務的方式來中斷執行此任務的線程。此方法傳回後,對 isDone() 的後續調用将始終傳回 true。如果此方法傳回 true,則對 isCancelled() 的後續調用将始終傳回 true。
  2. boolean isCancelled():如果在任務正常完成前将其取消,則傳回 true。
  3. boolean isDone():如果任務已完成,則傳回 true。 可能由于正常終止、異常或取消而完成,在所有這些情況中,此方法都将傳回 true。
  4. V get()throws InterruptedException,ExecutionException:如有必要,等待計算完成,然後擷取其結果。
  5. V get(long timeout,TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException: 如有必要,最多等待為使計算完成所給定的時間之後,擷取其結果(如果結果可用)。

總的來說Future提供了三種功能:

  1. 判斷任務是否完成;
  2. 能夠中斷任務;
  3. 能夠擷取任務執行結果。

重點:

RunnableFuture繼承了Runnable接口和Future接口,而FutureTask實作了RunnableFuture接口。

FutureTask的實作:

public class FutureTask<V> implements RunnableFuture<V>      

RunnableFuture接口的實作:

public interface RunnableFuture<V> extends Runnable, Future<V> {    void run();
}      

FutureTask是Future接口的一個唯一實作類。

除了可以用Thread包裝FutureTask外,還有另一種使用方法:

ExecutorService executor = Executors.newCachedThreadPool();
FutureTask<Integer> futureTask = new FutureTask<Integer>(new Callable<Integer>() {
    @Override    public Integer call() throws Exception {
        // do something        return null;
    }
});
executor.submit(futureTask);Integer result = futureTask.get();      

這裡用到了Executor 架構。

->next();

3. 關于ExecutorService,Executor,Excutors,ThreadPoolExcetor

Executor架構在Java 5中被引入,Executor 架構是一個根據一組執行政策調用、排程、執行和控制的異步任務的架構。

在說Executor 架構之前我們需要引入一個新的概念——線程池(ThreadPoolExecutor):

public ThreadPoolExecutor(intcorePoolSize,        int maximumPoolSize,        long keepAliveTime,
        TimeUnit unit,
        BlockingQueue<Runnable> workQueue,
        ThreadFactory threadFactory,
        RejectedExecutionHandler handler)      

ThreadPoolExecutor是Executors類的底層實作。

在JDK幫助文檔中,有如此一段話:

“強烈建議程式員使用較為友善的 Executors 工廠方法 Executors.newCachedThreadPool()(×××線程池,可以進行自動線程回收)、Executors.newFixedThreadPool(int)(固定大小線程池)和 Executors.newSingleThreadExecutor()(單個背景線程),它們均為大多數使用場景預定義了設定。”

那麼ExecutorService,Excetor,Excutors都是什麼?

Excetor是一個抽象層面的核心接口:

public interface Executor {    void execute(Runnable command);
}      

ExecutorService 接口 對 Executor 接口進行了擴充,提供了傳回 Future 對象,終止,關閉線程池等方法。

public interface ExecutorService extends Executor {    void shutdown();
    <T> Future<T> submit(Callable<T> task);
    <T> Future<T> submit(Runnable task, T result);
    <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException;
}      
public class Executors {    public static ExecutorService newFixedThreadPool(int nThreads) {        return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());
        }        
     public static ExecutorService newCachedThreadPool() {        return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>());
        }
}