JAVA並行非同步編程,線程池+FutureTask+callable+ExecutorService__Thinking

來源:互聯網
上載者:User

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

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

在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);    }  }

    結果如下

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

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

 

那麼有沒有什麼辦法來減少main主線程的阻塞時間呢。能不能讓這幾個操作並行進行呢。如果是並行運行帶來什麼好處呢。

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

 

java為我們提供了多線程機制,利用多線程我們可以實現方法的並行運算,實現多線程的辦法,實現Runnable介面重新run,繼承Thread 重寫run;因為run方法的並沒有傳回值,我們手動的去建立大量的線程並且維護線程是件很討厭的事情,並且建立線程也是非常耗費資源的操作,能不能有一個池子來幫我們管理線程呢。有沒有一個類能夠透明的去進行透明並發的非同步作業呢。這個在JDK1.5之前是沒有的,在1,5之後出現了一個新包,專門為並發而開發的包,使用並發包中提供的類和介面,將很輕易的實現。並發編程。

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

轉:http://liuyieyer.iteye.com/blog/2083111

附: 線程池工程原理

 多線程技術主要解決處理器單元內多個線程執行的問題,它可以顯著減少處理器單元的閑置時間,增加處理器單元的吞吐能力。         假設一個伺服器完成一項任務所需時間為:T1 建立線程時間,T2 線上程中執行任務的時間,T3 銷毀線程時間。     如果:T1 + T3 遠大於 T2,則可以採用線程池,以提高伺服器效能。                 一個線程池包括以下四個基本組成部分:                 1、線程池管理器(ThreadPool):用於建立並管理線程池,包括 建立線程池,銷毀線程池,添加新任務;                 2、背景工作執行緒(PoolWorker):線程池中線程,在沒有任務時處於等待狀態,可以迴圈的執行任務;                 3、任務介面(Task):每個任務必須實現的介面,以供背景工作執行緒調度任務的執行,它主要規定了任務的入口,任務執行完後的收尾工作,任務的執行狀態等;                 4、任務隊列(taskQueue):用於存放沒有處理的任務。提供一種緩衝機制。                      線程池技術正是關注如何縮短或調整T1,T3時間的技術,從而提高伺服器程式效能的。它把T1,T3分別安排在伺服器程式的啟動和結束的時間段或者一些閒置時間段,這樣在伺服器程式處理客戶請求時,不會有T1,T3的開銷了。     線程池不僅調整T1,T3產生的時間段,而且它還顯著減少了建立線程的數目,看一個例子:     假設一個伺服器一天要處理50000個請求,並且每個請求需要一個單獨的線程完成。線上程池中,線程數一般是固定的,所以產生線程總數不會超過線程池中線程的數目,而如果伺服器不利用線程池來處理這些請求則線程總數為50000。一般線程池大小是遠小於50000。所以利用線程池的伺服器程式不會為了建立50000而在處理請求時浪費時間,從而提高效率。

    代碼實現中並沒有實現任務介面,而是把Runnable對象加入到線程池管理器(ThreadPool),然後剩下的事情就由線程池管理器(ThreadPool)來完成了

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.