1. 程式人生 > >建立執行緒Future/FutureTask/Callable,且併發

建立執行緒Future/FutureTask/Callable,且併發

建立執行緒:Callable+Future Callable+FutureTask

> Android併發(多執行緒相關)-Future,FutureTask和Callable
Android併發程式設計之白話文詳解Future,FutureTask和Callable-- http://blog.csdn.net/nugongahou110/article/details/49967495
Java多執行緒程式設計:Callable、Future和FutureTask淺析- https://blog.csdn.net/javazejian/article/details/50896505
  
-- 建立執行緒的方式有兩種,一種是實現Runnable介面,另一種是繼承Thread

,但是這兩種方式都有個缺點,那就是在任務執行完成之後無法獲取返回結果
public interface Runnable {  
    public abstract void run();  

}  
-- 如果需要獲取執行結果,就必須通過共享變數或者使用執行緒通訊的方式來達到效果,這樣使用起來就比較麻煩。自從Java 1.5開始,就提供了Callable和Future,通過它們可以在任務執行完畢之後得到任務執行結果。Callable、Future和FutureTask三個類的使用方法。Executor框架結構中提到的Callable介面和Future介面。從JAVA SE 5.0開始引入了Callable和Future。
Callable的介面:Callable位於java.util.concurrent包下,它也是一個介面
public interface Callable<V> {   
  V call() throws Exception;   
}  
這是一個泛型介面,call()函式返回的型別就是傳遞進來的V型別。

 那麼怎麼使用Callable呢?一般情況下是配合ExecutorService來使用的,在ExecutorService介面中聲明瞭若干個submit方法的過載版本:
<T> Future<T> submit(Callable<T> task);
<T> Future<T> submit(Runnable task, T result);
Future<?> submit(Runnable task);
一般情況下我們使用第一個submit方法和第三個submit方法,第二個submit方法很少使用

-- Future中的方法有:


   Future就是對於具體的Runnable或者Callable任務的執行結果進行取消、查詢是否完成、獲取結果。必要時可以通過get方法獲取執行結果,該方法會阻塞直到任務返回結果。
  1.cancel方法用來取消任務,如果取消任務成功則返回true,如果取消任務失敗則返回false。引數mayInterruptIfRunning表示是否允許取消正在執行卻沒有執行完畢的任務,如果設定true,則表示可以取消正在執行過程中的任務。如果任務已經完成,則無論mayInterruptIfRunning為true還是false,此方法肯定返回false,即如果取消已經完成的任務會返回false;如果任務正在執行,若mayInterruptIfRunning設定為true,則返回true,若mayInterruptIfRunning設定為false,則返回false;如果任務還沒有執行,則無論mayInterruptIfRunning為true還是false,肯定返回true。
  2.isCancelled方法表示任務是否被取消成功,如果在任務正常完成前被取消成功,則返回 true。
  3.isDone方法表示任務是否已經完成,若任務完成,則返回true;
  4.get()方法用來獲取執行結果,這個方法會產生阻塞,會一直等到任務執行完畢才返回;
  5.get(long timeout, TimeUnit unit)用來獲取執行結果,如果在指定時間內,還沒獲取到結果,就直接返回null。
Future提供了三種功能:1.任務是否完成;2.能夠中斷介面;3.能夠獲取任務執行結果。
Future類位於java.util.concurrent包下,它是一個介面:
public interface Future<V> {
    boolean cancel(booleanmayInterruptIfRunning);
    boolean isCancelled();
    boolean isDone();
    V get() throws InterruptedException, ExecutionException;
    V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}

-- FutureTask的實現:FutureTask類實現了RunnableFuture介面
public interface RunnableFuture<V> extends Runnable, Future<V> {
    void run();
}
public class FutureTask<V> implements RunnableFuture<V>{}
 可以看出RunnableFuture繼承了Runnable介面和Future介面,而FutureTask實現了RunnableFuture介面。所以它既可以作為Runnable被執行緒執行,又可以作為Future得到Callable的返回值。

FutureTask提供了2個構造器:
public FutureTask(Callable<V> callable) {
}
public FutureTask(Runnable runnable, V result) {
}

-- Future<Object> future = executor.submit(harReturnValuetask);
try {
     Object s = future.get();
} catch (InterruptedException e) {
    // 處理中斷異常
} catch (ExecutionException e) {
    // 處理無法執行任務異常
} finally {
    // 關閉執行緒池
    executor.shutdown();
}

> Callable+Future Callable+FutureTask執行執行緒示例
import java.util.concurrent.Callable;  
public class CallableDemo implements Callable<Integer> {      
    private int sum;  
    @Override  
    public Integer call() throws Exception {  
        System.out.println("Callable子執行緒開始計算啦!");  
        Thread.sleep(2000);  
          
        for(int i=0 ;i<5000;i++){  
            sum=sum+i;  
        }  
        System.out.println("Callable子執行緒計算結束!");  
        return sum;  
    }  

1.使用Callable+Future獲取執行結果
public class CallableTest {     
    public static void main(String[] args) {  
        //建立執行緒池  
        ExecutorService es = Executors.newSingleThreadExecutor();  
        //建立Callable物件任務  
        CallableDemo calTask=new CallableDemo();  
        //提交任務並獲取執行結果  
        Future<Integer> future =es.submit(calTask);  
        //關閉執行緒池  
        es.shutdown();  
        try {  
            Thread.sleep(2000);  
        System.out.println("主執行緒在執行其他任務");  
          
        if(future.get()!=null){  
            //輸出獲取到的結果  
            System.out.println("future.get()-->"+future.get());  
        }else{  
            //輸出獲取到的結果  
            System.out.println("future.get()未獲取到結果");  
        }  
          
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
        System.out.println("主執行緒在執行完成");  
    }  
}  

2.使用Callable+FutureTask獲取執行結果
public class CallableTest {    
    public static void main(String[] args) {  
//      //建立執行緒池  
//      ExecutorService es = Executors.newSingleThreadExecutor();  
//      //建立Callable物件任務  
//      CallableDemo calTask=new CallableDemo();  
//      //提交任務並獲取執行結果  
//      Future<Integer> future =es.submit(calTask);  
//      //關閉執行緒池  
//      es.shutdown();  
          
        //建立執行緒池  
        ExecutorService es = Executors.newSingleThreadExecutor();  
        //建立Callable物件任務  
        CallableDemo calTask=new CallableDemo();  
        //建立FutureTask  
        FutureTask<Integer> futureTask=new FutureTask<>(calTask);  
        //執行任務  
        es.submit(futureTask);  
        //關閉執行緒池  
        es.shutdown();  
        try {  
            Thread.sleep(2000);  
            System.out.println("主執行緒在執行其他任務");  
          
            if(futureTask.get()!=null){  
                //輸出獲取到的結果  
                System.out.println("futureTask.get()-->"+futureTask.get());  
            }else{  
                //輸出獲取到的結果  
                System.out.println("futureTask.get()未獲取到結果");  
            }  
          
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
        System.out.println("主執行緒在執行完成");  
    }  
}  

總結:
     如果為了可取消性而使用 Future 但又不提供可用的結果,則可以宣告 Future<?> 形式型別、並返回 null 作為底層任務的結果。
     Future 是有其侷限性的。Future 主要功能在於獲取任務執行結果和對非同步任務的控制。但如果要獲取批量任務的執行結果,從上面的例子我們已經可以看到,單使用 Future 是很不方便的。其原因在於:一是我們沒有好的方法去獲取第一個完成的任務;二是 Future.get 是阻塞方法,使用不當會造成執行緒的浪費。解決第一個問題可以用 CompletionService 解決,CompletionService 提供了一個 take() 阻塞方法,用以依次獲取所有已完成的任務。對於第二個問題,可以用 Google Guava 庫所提供的 ListeningExecutorService 和 ListenableFuture 來解決。
     除了獲取批量任務執行結果時不便,Future 另外一個不能做的事便是防止任務的重複提交。要做到這件事就需要 Future 最常見的一個實現類 FutureTask 了。《Java Concurrency in Practice》中的例子“Listing 5.19. Final Implementation of Memoizer”便展示瞭如何使用 FutureTask 做到這一點。
 

相關推薦

建立執行Future/FutureTask/Callable併發

建立執行緒:Callable+Future Callable+FutureTask > Android併發(多執行緒相關)-Future,FutureTask和Callable Android併發程式設計之白話文詳解Future,FutureTask和Callable

執行——Future,Runnable,Callable,FutureTask

Runnable介面是常規的執行緒介面,執行緒執行的業務邏輯主體放在 其void Run()方法裡面,繼承此介面實現此方法。 Callable介面也是一個常規介面,執行緒執行的業務邏輯主體放在 其v Call()方法裡面,只不過這個方法有返回值V(泛型),也可以丟擲異常, FutureTask

java多執行FutureCallable類的解釋與使用

一,描述     ​在多執行緒下程式設計的時候,大家可能會遇到一種需求,就是我想在我開啟的執行緒都結束時,同時獲取每個執行緒中返回的資料然後再做統一處理,在這樣的需求下,Future與Callable的組合就派上了很大的用場。也有人會說,我可以使用同步來完成這個需求啊,一

使用CallableFuture建立執行

Java建立執行緒主要有三種方式:   1、繼承Thread類   2、實現Runnable介面   3、使用Callable和Future建立執行緒     參考地址:https://www.cnblogs.com/yeya/p/10183366.html 一、繼承Thread

java多執行FutureFutureTask使用示例返回非同步的結果

1、Future、FutureTask介紹 Future是一個介面,該介面用來返回非同步的結果。 FutureTask是一個類,是Future 的一個實現。 2、主要方法 future.get(); 或者 future.get(10000, Ti

使用FutureCallable建立執行

建立執行緒還可以使用 Future和Callabe來建立執行緒。 Future就是對於具體的Runnable或者Callable任務的執行結果進行取消、查詢是否完成、獲取結果。必要時可以通過get方法獲取執行結果,該方法會阻塞直到任務返回結果。   Futu

執行futureTask(future,callable)例項,jdbc資料多執行查詢

最近遇到一個這樣的功能要求。在查詢資料時,由於查詢的資料量比較大,一次查詢(一條SQL語句中包含太多的條件)查詢起來很慢,大約要10S左右才能查詢出來,這樣體驗太不好了,需要進行優化。今天想了想,打算採用在後端把一條SQL進行拆分,拆分成為多條SQL語句,再拋給多個執行緒去

建立執行的第三種方式CallableFuture CompletionService

前面已經指出通過實現Runnable時,Thread類的作用就是將run()方法包裝成執行緒執行體,那麼是否可以直接把任意方法都包裝成執行緒執行體呢?Java目前不行,但其模仿者C#中是可以的. Callabel介面可以看成是Runnable介面的增強版,只不過其執行緒

三種Java建立執行的方式(Callable,FutureTask

Java執行緒具有併發性和非同步性,可以說執行緒是輕量級別的程序,java中執行緒和現代作業系統中的程序排程都是採用採用搶佔式執行。但執行緒和程序最大的區別是:一個程序中的多個程序共享這個程序的記憶體

執行間操作無效: 從不是建立控制元件“XXX”的執行訪問它 [Winform]執行間操作無效從不是建立控制元件的執行訪問它的幾個解決方案async和await?

方法1  Invoke((MethodInvoker)(()=>{XXX.Text = message;}));   方法2 取消跨執行緒檢查 Control.CheckForIllegalCrossThreadCalls = false;  

RT-Thread 讀後感2——建立執行(定義執行的棧定義執行函式定義執行控制塊執行初始化函式)

1. 定義執行緒的棧 多執行緒作業系統中,每個執行緒都是獨立的,互不干擾,所以要為每個執行緒分配獨立的棧空間,這個棧空間通常是一個預先定義好的全域性陣列, 也可以是動態分配的一段記憶體空間,但它們都存在於 RAM 中。定義兩個執行緒棧如下: // 定義執行緒棧 大小設定為512 rt_ui

執行池ThreadPoolExecutor分析: 執行池是什麼時候建立執行佇列中的任務是什麼時候取出來的?

  帶著幾個問題進入原始碼分析: 執行緒池是什麼時候建立執行緒的? 任務runnable task是先放到core到maxThread之間的執行緒,還是先放到佇列? 佇列中的任務是什麼時候取出來的? 什麼時候會觸發reject策略? core到maxThread之間的執行緒什麼時候會di

RT-Thread 讀後感2——建立執行(定義執行的棧定義執行函式)

1. 定義執行緒的棧 多執行緒作業系統中,每個執行緒都是獨立的,互不干擾,所以要為每個執行緒分配獨立的棧空間,這個棧空間通常是一個預先定義好的全域性陣列, 也可以是動態分配的一段記憶體空間,但它們都存在於 RAM 中。定義兩個執行緒棧如下: // 定義執行緒棧 大小設定為

執行建立執行的方式之一:實現Callable介面(三)

對於多執行緒,大家並不陌生,對於如何建立執行緒也是輕車熟路,對於使用new thread和實現runable介面的方式,不再多說。這篇博文我們介紹第三種:實現Callable介面。 Callable介面 介面定義: @FunctionalInterface

建立執行後為什麼關閉了執行控制代碼執行還是可以執行?

主執行緒只要擁有執行緒控制代碼,事後就可以對執行緒執行某些操作,比如查詢執行緒狀態等等,靠的就是控制代碼,如果沒有控制代碼,系統就無從知道要查的是那個執行緒的狀態。但保持這個控制代碼不關閉,並不是執行緒執行的條件。       &nbs

通過Executors建立執行池存在的弊端如何使用ThreadPoolExecutor建立執行

Java通過Executors提供四種執行緒池,分別為:1)newCachedThreadPool 建立一個可快取執行緒池,如果執行緒池長度超過處理需要,可靈活回收空閒執行緒,若無可回收,則新建執行緒。

執行Future+Callable實現併發查詢

對於所查詢的資料比較耗時,資料位於不同的資料來源中,可以通過併發查詢的方式加快獲取想要的資料。記錄專案中用到的方法。 package com.lancy.interfaces.util; import java.util.concurrent.Calla

Java多執行 - Future模式轉換成ListenableFuture模式以及AsyncRestTemplate的原理

一、AsyncRestTemplate Demo: spring4.0提供了RestTemplate的非同步呼叫版本AsyncRestTemplate,用其進行非同步呼叫的demo如下: MultiValueMap headers = new LinkedMultiValueMa

Java併發程式設計之執行池、CallableFuture使用

知識儲備 收藏幾篇好文章: 目錄結構 Callable和Future使用 執行緒池使用 Callable和Future使用 多執行緒實現方式很多,分為兩類:1、沒有返回值的;2、有返回值的。 針對“沒有返回值的”這類可以參

不推薦使用Executors建立執行推薦通過ThreadPoolExecutor方式建立

執行緒池不允許使用Executors去建立,而是通過ThreadPoolExecutor的方式,這樣的處理方式讓寫的同學更加明確執行緒池的執行規則,規避資源耗盡的風險。 說明:Executors各個方法的弊端: 1)newFixedThreadPool和newSingleThreadExecut