最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解Java Callable接口實現(xiàn)多線程的方式

 更新時間:2020年04月22日 14:56:03   作者:Ai布可思咦  
這篇文章主要介紹了詳解Java Callable接口實現(xiàn)多線程的方式,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

在Java 1.5以前,創(chuàng)建線程的2種方式,一種是直接繼承Thread,另外一種就是實現(xiàn)Runnable接口。無論我們以怎樣的形式實現(xiàn)多線程,都需要調(diào)用Thread類中的start方法去向操作系統(tǒng)請求io,cup等資源。因為線程run方法沒有返回值,如果需要獲取執(zhí)行結(jié)果,就必須通過共享變量或者使用線程通信的方式來達(dá)到效果,這樣使用起來就比較麻煩。

而自從Java 1.5開始,就提供了Callable和Future,通過它們可以在任務(wù)執(zhí)行完畢之后得到任務(wù)執(zhí)行結(jié)果。

Callable和Future介紹

Callable接口代表一段可以調(diào)用并返回結(jié)果的代碼;Future接口表示異步任務(wù),是還沒有完成的任務(wù)給出的未來結(jié)果。所以說Callable用于產(chǎn)生結(jié)果,F(xiàn)uture用于獲取結(jié)果。

Callable接口使用泛型去定義它的返回類型。Executors類提供了一些有用的方法在線程池中執(zhí)行Callable內(nèi)的任務(wù)。由于Callable任務(wù)是并行的(并行就是整體看上去是并行的,其實在某個時間點只有一個線程在執(zhí)行),我們必須等待它返回的結(jié)果。
java.util.concurrent.Future對象為我們解決了這個問題。在線程池提交Callable任務(wù)后返回了一個Future對象,使用它可以知道Callable任務(wù)的狀態(tài)和得到Callable返回的執(zhí)行結(jié)果。Future提供了get()方法讓我們可以等待Callable結(jié)束并獲取它的執(zhí)行結(jié)果。

Callable與Runnable

java.lang.Runnable吧,它是一個接口,在它里面只聲明了一個run()方法:

public interface Runnable {

  public abstract void run();

}  

由于run()方法返回值為void類型,所以在執(zhí)行完任務(wù)之后無法返回任何結(jié)果?! allable位于java.util.concurrent包下,它也是一個接口,在它里面也只聲明了一個方法,只不過這個方法叫做call():

public interface Callable<V> {
  /**
   * Computes a result, or throws an exception if unable to do so.
   * @return computed result
   * @throws Exception if unable to compute a result
   */
  V call() throws Exception;
}  

可以看到,這是一個泛型接口,call()函數(shù)返回的類型就是傳遞進(jìn)來的V類型。

那么怎么使用Callable呢?

一般情況下是配合ExecutorService來使用的,在ExecutorService接口中聲明了若干個submit方法的重載版本:

 <T> Future<T> submit(Callable<T> task);

<T> Future<T> submit(Runnable task, T result);

Future<?> submit(Runnable task);

Future

Future就是對于具體的Runnable或者Callable任務(wù)的執(zhí)行結(jié)果進(jìn)行取消、查詢是否完成、獲取結(jié)果。必要時可以通過get方法獲取執(zhí)行結(jié)果,該方法會阻塞直到任務(wù)返回結(jié)果。  

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

:<T> Future<T> submit(Callable<T> task);

<T> Future<T> submit(Runnable task, T result);

Future<?> submit(Runnable task);

在Future接口中聲明了5個方法,下面依次解釋每個方法的作用:

cancel方法  用來取消任務(wù),如果取消任務(wù)成功則返回true,如果取消任務(wù)失敗則返回false。參數(shù)mayInterruptIfRunning表示是否允許取消正在執(zhí)行卻沒有執(zhí)行完畢的任務(wù),如果設(shè)置true,則表示可以取消正在執(zhí)行過程中的任務(wù)。如果任務(wù)已經(jīng)完成,則無論mayInterruptIfRunning為true還是false,此方法肯定返回false,即如果取消已經(jīng)完成的任務(wù)會返回false;如果任務(wù)正在執(zhí)行,若mayInterruptIfRunning設(shè)置為true,則返回true,若mayInterruptIfRunning設(shè)置為false,則返回false;如果任務(wù)還沒有執(zhí)行,則無論mayInterruptIfRunning為true還是false,肯定返回true。

isCancelled方法  表示任務(wù)是否被取消成功,如果在任務(wù)正常完成前被取消成功,則返回 true。

isDone方法  表示任務(wù)是否已經(jīng)完成,若任務(wù)完成,則返回true;

get()方法   用來獲取執(zhí)行結(jié)果,這個方法會產(chǎn)生阻塞,會一直等到任務(wù)執(zhí)行完畢才返回;

get(long timeout, TimeUnit unit)   用來獲取執(zhí)行結(jié)果,如果在指定時間內(nèi),還沒獲取到結(jié)果,就直接返回null。

也就是說Future提供了三種功能: 

1)判斷任務(wù)是否完成;

2)能夠中斷任務(wù);

3)能夠獲取任務(wù)執(zhí)行結(jié)果。

Future用于表示異步計算的結(jié)果。它的實現(xiàn)類有java.util.concurrent.FutureTask<V>和 javax.swing.SwingWorker<T,V>,Android平臺上如果不想分支線程阻塞主線程,又想取得分支線程的執(zhí)行結(jié)果,可以用FutureTask。

FutureTask

Java的類是單繼承的設(shè)計,如果采用繼承Thread的方式實現(xiàn)多線程,則不能繼承其他的類,采用接口能夠更好的實現(xiàn)數(shù)據(jù)共享

FutureTask實現(xiàn)了RunnableFuture接口,這個接口的定義如下:

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

可以看到這個接口實現(xiàn)了Runnable和Future接口,接口中的具體實現(xiàn)由FutureTask來實現(xiàn)。這個類的兩個構(gòu)造方法如下 :

public FutureTask(Callable<V> callable) { 
    if (callable == null) 
      throw new NullPointerException(); 
    sync = new Sync(callable); 
} 
  
public FutureTask(Runnable runnable, V result) { 
 sync = new Sync(Executors.callable(runnable, result)); 
}

如上提供了兩個構(gòu)造函數(shù),一個以Callable為參數(shù),另外一個以Runnable為參數(shù)。這些類之間的關(guān)聯(lián)對于任務(wù)建模的辦法非常靈活,允許你基于FutureTask的Runnable特性(因為它實現(xiàn)了Runnable接口),把任務(wù)寫成Callable,然后封裝進(jìn)一個由執(zhí)行者調(diào)度并在必要時可以取消的FutureTask。

FutureTask可以由執(zhí)行者調(diào)度,這一點很關(guān)鍵。它對外提供的方法基本上就是Future和Runnable接口的組合:get()、cancel、isDone()、isCancelled()和run(),而run()方法通常都是由執(zhí)行者調(diào)用,我們基本上不需要直接調(diào)用它。FutureTask類同時又實現(xiàn)了Runnable接口,所以可以直接提交給Thread、Executors執(zhí)行:

public class CallableAndFuture { 
    public static void main(String[] args) { 
      Callable<Integer> callable = new Callable<Integer>() { 
        public Integer call() throws Exception { 
          return new Random().nextInt(100); 
        } 
      }; 

    FutureTask<Integer> future = new FutureTask<Integer>(callable); 
    new Thread(future).start(); 
 
    try { 
      Thread.sleep(5000);// 可能做一些事情 
 
      int result = future.get()); 
 
    } catch (InterruptedException e) { 
      e.printStackTrace(); 
    } catch (ExecutionException e) { 
      e.printStackTrace(); 
    } 
  } 
} 
public class CallableAndFuture { 
  public static void main(String[] args) { 
 
    //ExecutorService.submit()
    ExecutorService threadPool = Executors.newSingleThreadExecutor(); 
    Future<Integer> future = threadPool.submit(new Callable<Integer>() { 
      public Integer call() throws Exception { 
        return new Random().nextInt(100); 
      } 
    }); 
 
    try { 
      Thread.sleep(5000);// 可能做一些事情 
 
      int result = future.get()); //Future.get()
 
    } catch (InterruptedException e) { 
      e.printStackTrace(); 
    } catch (ExecutionException e) { 
      e.printStackTrace(); 
    } 
  } 

如果要執(zhí)行多個帶返回值的任務(wù),并取得多個返回值,可用CompletionService:

CompletionService相當(dāng)于Executor加上BlockingQueue,使用場景為當(dāng)子線程并發(fā)了一系列的任務(wù)以后,主線程需要實時地取回子線程任務(wù)的返回值并同時順序地處理這些返回值,誰先返回就先處理誰。

public class CallableAndFuture { 
  public static void main(String[] args) { 
    ExecutorService threadPool = Executors.newCachedThreadPool(); 
    CompletionService<Integer> cs = new ExecutorCompletionService<Integer>(threadPool); 
    for(int i = 1; i < 5; i++) { 
      final int taskID = i; 
      //CompletionService.submit()
      cs.submit(new Callable<Integer>() { 
        public Integer call() throws Exception { 
          return taskID; 
        } 
      }); 
    } 
    // 可能做一些事情 
    for(int i = 1; i < 5; i++) { 
      try { 
        int result = cs.take().get()); //CompletionService.take()返回Future
      } catch (InterruptedException e) { 
        e.printStackTrace(); 
      } catch (ExecutionException e) { 
        e.printStackTrace(); 
      } 
    } 
  } 
}  

或者不使用CompletionService:先創(chuàng)建一個裝Future類型的集合,用Executor提交的任務(wù)返回值添加到集合中,最后便利集合取出數(shù)據(jù)。

區(qū)別:

Future集合方法,submit的task不一定是按照加入自己維護(hù)的list順序完成的。從list中遍歷的每個Future對象并不一定處于完成狀態(tài),這時調(diào)用get()方法就會被阻塞住,如果系統(tǒng)是設(shè)計成每個線程完成后就能根據(jù)其結(jié)果繼續(xù)做后面的事,這樣對于處于list后面的但是先完成的線程就會增加了額外的等待時間。

而CompletionService的實現(xiàn)是維護(hù)一個保存Future對象的BlockingQueue。只有當(dāng)這個Future對象狀態(tài)是結(jié)束的時候,才會加入到這個Queue中,take()方法其實就是Producer-Consumer中的Consumer。它會從Queue中取出Future對象,如果Queue是空的,就會阻塞在那里,直到有完成的Future對象加入到Queue中。

所以,先完成的必定先被取出。這樣就減少了不必要的等待時間。

到此這篇關(guān)于詳解Java Callable接口實現(xiàn)多線程的方式的文章就介紹到這了,更多相關(guān)Java Callable接口多線程內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 聊聊java多線程創(chuàng)建方式及線程安全問題

    聊聊java多線程創(chuàng)建方式及線程安全問題

    線程被稱為輕量級進(jìn)程,是程序執(zhí)行的最小單位,它是指在程序執(zhí)行過程中,能夠執(zhí)行代碼的一個執(zhí)行單位。接下來通過本文給大家介紹java多線程創(chuàng)建方式及線程安全問題,感興趣的朋友一起看看吧
    2022-01-01
  • SpringBoot項目中使用@Scheduled讀取動態(tài)參數(shù)

    SpringBoot項目中使用@Scheduled讀取動態(tài)參數(shù)

    這篇文章主要介紹了SpringBoot項目中使用@Scheduled讀取動態(tài)參數(shù),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • SpringBoot使用@Autowired為多實現(xiàn)的接口注入依賴

    SpringBoot使用@Autowired為多實現(xiàn)的接口注入依賴

    這篇文章主要介紹了SpringBoot使用@Autowired為多實現(xiàn)的接口注入依賴,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • Java中的FileInputStream 和 FileOutputStream 介紹_動力節(jié)點Java學(xué)院整理

    Java中的FileInputStream 和 FileOutputStream 介紹_動力節(jié)點Java學(xué)院整理

    FileInputStream 是文件輸入流,它繼承于InputStream。FileOutputStream 是文件輸出流,它繼承于OutputStream。接下來通過本文給大家介紹Java中的FileInputStream 和 FileOutputStream,需要的朋友可以參考下
    2017-05-05
  • Java使用Gateway自定義負(fù)載均衡過濾器

    Java使用Gateway自定義負(fù)載均衡過濾器

    這篇文章主要介紹了Java使用Gateway自定義負(fù)載均衡過濾器,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • 關(guān)于spring三級緩存的解讀

    關(guān)于spring三級緩存的解讀

    Spring三級緩存解決循環(huán)依賴、AOP和多線程問題,包括singletonObjects、earlySingletonObjects和singletonFactories三層緩存,通過不同方法獲取bean并解決這些問題
    2025-02-02
  • java中ArrayList的兩種排序方法實例

    java中ArrayList的兩種排序方法實例

    ArrayList是一個數(shù)組隊列,相當(dāng)于 動態(tài)數(shù)組,與Java中的數(shù)組相比,它的容量能動態(tài)增長,這篇文章主要給大家介紹了關(guān)于java中ArrayList的兩種排序方法,需要的朋友可以參考下
    2021-07-07
  • Mybatis往Mapper.xml文件中傳遞多個參數(shù)問題

    Mybatis往Mapper.xml文件中傳遞多個參數(shù)問題

    這篇文章主要介紹了Mybatis往Mapper.xml文件中傳遞多個參數(shù)問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • Java面向?qū)ο笕筇匦约岸鄳B(tài)解析

    Java面向?qū)ο笕筇匦约岸鄳B(tài)解析

    這篇文章主要介紹了Java面向?qū)ο笕筇匦约岸鄳B(tài)詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-09-09
  • 深入淺析Mybatis與Hibernate的區(qū)別與用途

    深入淺析Mybatis與Hibernate的區(qū)別與用途

    這篇文章主要介紹了Mybatis與Hibernate的區(qū)別與用途的相關(guān)資料,需要的朋友可以參考下
    2017-10-10

最新評論

丰原市| 峨眉山市| 皮山县| 湘乡市| 双柏县| 海晏县| 盖州市| 微山县| 连州市| 南陵县| 娱乐| 五峰| 尼勒克县| 滦南县| 枝江市| 榆中县| 高尔夫| 柳河县| 东乡族自治县| 吴忠市| 广宗县| 凤翔县| 舟曲县| 新宾| 江陵县| 塘沽区| 时尚| 炎陵县| 广灵县| 海兴县| 灌云县| 南充市| 巴青县| 闻喜县| 吴旗县| 西吉县| 靖西县| 会理县| 石棉县| 广安市| 四子王旗|