FutureTask 使用場景介紹

可以通過其提供的get方法,在FutureTask不同的狀態下,以阻塞或者直接返回的方式或者結果。

FutureTask實現了Future和Runnable接口。以FutureTask是否調用了run方法,可以簡單分爲三種狀態

1. 未啓動。 run方法未執行。

2. 已啓動。 run方法執行。

3. 已完成。 run方法正常執行完畢,或者調用cancel取消,或者run方法執行過程中拋出異常。

 

強調以上不同狀態的特性,是爲了突出一下這個場景的使用:多線程執行任務,任務只被執行一次

FutureTask正常執行完成會返回值(不會再次執行),若中斷,正在中斷,或者取消時拋出異常。

看下代碼,落地下:

Class TaskHandler{
    // 記錄執行過的任務
    private final ConcurrentHashMap<Object,Future<String>> taskCache = new ConcurrentHashMap<Object,Future<String>>// hashet用Collections包裝下也可以用,再根據put的返回,判斷該任務已經存在。
    public String execute(final String taskName) throws ExecutionException, InterruptException {
        while (true) {
            Future<String> future = taskCache.get(taskName);
            if(future == null) {
                Callable<String> task = new Callable<String>() {
                    @Override
                    public String call() throws InterruptedException{
                        return taskName;
                    }
                };
            FutureTask<String> futureTask = new FutureTask<String>(task);
            future = taskCache.put(taskName, futureTask);
            if(future == null) {
                future = futureTask;
                futureTask.run();
            }
            }
            try {
                future.get();
            } catch(CancellationException e) {
                // 這個是get方法throw出來的異常 這裏有兩種異常CancellationException ExecutionException 只處理CancellationException,是因爲這個異常是主動取消任務的,我們需要將其從taskCache中去除掉
                taskCache.remove(taskName, future);
            }
        }
    }
}

以上代碼有個小細節,這裏指出一下。taskCache.remove(taskName, future),可不可以用taskCache.remove(taskName)?答案是可以的,前者是找到taskName對應的index後,調用future的equal判斷是否是同一個對象,後者通過對taskName指針地址或者hashcode進行判斷是否是同一個對象的。推薦使用第二種remove方法,因爲String重寫了equal和hashcode。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章