JAVA並行異步編程,線程池+FutureTask

java 在JDK1.5中引入一個新的併發包java.util.concurrent 該包專門爲java處理併發而書寫。css

在java中熟悉的使用多線程的方式爲兩種?繼續Thread類,實現Runnale。兩種方式簡單方便。java

在Jdk1.5以後其實有第三種方式實現方式,採用併發包中的 Callable接口 FuruteTask類 以及 ExecutorService接口。編程

說新的實現方式以前先來講討論一下傳統的java執行過程多線程

首先一個簡單的程序一個方法生成隨機數,在生成隨機數的方法執行中,睡眠1s模擬方法調用時候的耗時,把結果放進集合中,最後算到總結果。併發

public 
 class Count{   public static void main(String[] args) throws InterruptedException {    long start = System.currentTimeMillis();   Count count = new Count();   List<Integer> res = new ArrayList<>();   res.add(count.random());   res.add(count.random());   res.add(count.random());   res.add(count.random());   int totle =0;   for (int i = 0; i < res.size(); i++) {    totle+=res.get(i);   }   long end = System.currentTimeMillis();   System.out.println("運算結束 耗時:"+(end-start)+"ms totle:"+totle );   System.out.println("退出main線程!");  }   int random() throws InterruptedException{    Thread.sleep(1000); //    return new Random().nextInt(100);   }  }

    結果以下dom

運算結束 耗時:4000ms  totle:66
退出main線程!

     在傳統的編寫中是單線程的操做,串行操做,當調用方法count.random(),main線程被阻塞起來,直到睡眠時間到達,自動喚醒main線程。異步

 

那麼有沒有什麼辦法來減小main主線程的阻塞時間呢?能不能讓這幾個操做並行進行呢?若是是並行運行帶來什麼好處呢?ide

並行帶來的好處,能夠減小比較多的方法執行時間,如random()方法並行計算,也就是說main線程的阻塞只有1s,阻塞時間減小75%post

 

java爲咱們提供了多線程機制,利用多線程咱們能夠實現方法的並行運算,實現多線程的辦法,實現Runnable接口從新run,繼承Thread 重寫run;由於run方法的並無返回值,咱們手動的去建立大量的線程而且維護線程是件很討厭的事情,而且建立線程也是很是耗費資源的操做,能不能有一個池子來幫咱們管理線程呢?有沒有一個類可以透明的去進行透明併發的異步操做呢?這個在JDK1.5以前是沒有的,在1,5以後出現了一個新包,專門爲併發而開發的包,使用併發包中提供的類和接口,將很輕易的實現。併發編程。spa

import java.util.ArrayList;
import java.util.List; import java.util.Random; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.FutureTask; public class TestMain {  public static void main(String[] args) throws InterruptedException, ExecutionException {   new TestMain().exec();  }  void exec() throws InterruptedException, ExecutionException{   //進行異步任務列表   List<FutureTask<Integer>> futureTasks = new ArrayList<FutureTask<Integer>>();   //線程池 初始化十個線程 和JDBC鏈接池是一個意思 實現重用   ExecutorService executorService = Executors.newFixedThreadPool(10);   long start = System.currentTimeMillis();   //相似與run方法的實現 Callable是一個接口,在call中手寫邏輯代碼   Callable<Integer> callable = new Callable<Integer>() {    @Override    public Integer call() throws Exception {     Integer res = new Random().nextInt(100);     Thread.sleep(1000);     System.out.println("任務執行:獲取到結果 :"+res);     return res;    }   };     for(int i=0;i<10;i++){    //建立一個異步任務    FutureTask<Integer> futureTask = new FutureTask<Integer>(callable);    futureTasks.add(futureTask);    //提交異步任務到線程池,讓線程池管理任務 特爽把。    //因爲是異步並行任務,因此這裏並不會阻塞    executorService.submit(futureTask);   }     int count = 0;  for (FutureTask<Integer> futureTask : futureTasks) {   //futureTask.get() 獲得咱們想要的結果   //該方法有一個重載get(long timeout, TimeUnit unit) 第一個參數爲最大等待時間,第二個爲時間的單位   count+= futureTask.get();  }  long end = System.currentTimeMillis();  System.out.println("線程池的任務所有完成:結果爲:"+count+",main線程關閉,進行線程的清理");  System.out.println("使用時間:"+(end-start)+"ms");  //清理線程池  executorService.shutdown();    } }

上述狀況若是不用異步並行,程序將至少睡眠10s

使用以後的結果

任務執行:獲取到結果 :99
任務執行:獲取到結果 :78 任務執行:獲取到結果 :52 任務執行:獲取到結果 :78 任務執行:獲取到結果 :97 任務執行:獲取到結果 :8 任務執行:獲取到結果 :97 任務執行:獲取到結果 :3 任務執行:獲取到結果 :78 任務執行:獲取到結果 :31 線程池的任務所有完成:結果爲:621,main線程關閉,進行線程的清理 使用時間:1004ms 

咱們試着把線程池的大小減小一半

任務執行:獲取到結果 :87
任務執行:獲取到結果 :60 任務執行:獲取到結果 :13 任務執行:獲取到結果 :18 任務執行:獲取到結果 :8 任務執行:獲取到結果 :86 任務執行:獲取到結果 :52 任務執行:獲取到結果 :4 任務執行:獲取到結果 :23 任務執行:獲取到結果 :16 線程池的任務所有完成:結果爲:367,main線程關閉,進行線程的清理 使用時間:2017ms 

好玩吧 時間延長了一半。

相關文章
相關標籤/搜索