中文字幕日韩精品一区二区免费_精品一区二区三区国产精品无卡在_国精品无码专区一区二区三区_国产αv三级中文在线

Java中線程池的實現(xiàn)原理是什么

這篇文章給大家介紹Java中線程池的實現(xiàn)原理是什么,內(nèi)容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

在徐匯等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強發(fā)展的系統(tǒng)性、市場前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務(wù)理念,為客戶提供做網(wǎng)站、成都做網(wǎng)站 網(wǎng)站設(shè)計制作按需策劃,公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),高端網(wǎng)站設(shè)計,成都營銷網(wǎng)站建設(shè),外貿(mào)網(wǎng)站建設(shè),徐匯網(wǎng)站建設(shè)費用合理。

線程池是什么?

我們可以利用java很容易創(chuàng)建一個新線程,同時操作系統(tǒng)創(chuàng)建一個線程也是一筆不小的開銷。所以基于線程的復用,就提出了線程池的概念,我們使用線程池創(chuàng)建出若干個線程,執(zhí)行完一個任務(wù)后,該線程會存在一段時間(用戶可以設(shè)定空閑線程的存活時間,后面會介紹),等到新任務(wù)來的時候就直接復用這個空閑線程,這樣就省去了創(chuàng)建、銷毀線程損耗。當然空閑線程也會是一種資源的浪費(所有才有空閑線程存活時間的限制),但總比頻繁的創(chuàng)建銷毀線程好太多。
下面是我的測試代碼

  /*
   * @TODO 線程池測試
   */
  @Test
  public void threadPool(){

    /*java提供的統(tǒng)計線程運行數(shù),一開始設(shè)置其值為50000,每一個線程任務(wù)執(zhí)行完
     * 調(diào)用CountDownLatch#coutDown()方法(其實就是自減1)
     * 當所有的線程都執(zhí)行完其值就為0
    */
    CountDownLatch count = new CountDownLatch(50000);
    long start = System.currentTimeMillis();
    Executor pool = Executors.newFixedThreadPool(10);//開啟線程池最多會創(chuàng)建10個線程
    for(int i=0;i<50000;i++){
      pool.execute(new Runnable() {
        @Override
        public void run() {
          System.out.println("hello");
          count.countDown();
        }
      });
    }

    while(count.getCount()!=0){//堵塞等待5w個線程運行完畢

    }
    long end = System.currentTimeMillis();
    System.out.println("50個線程都執(zhí)行完了,共用時:"+(end-start)+"ms");
  }


  /**
   *@TODO 手動創(chuàng)建線程測試 
   */
  @Test
  public void thread(){
    CountDownLatch count = new CountDownLatch(50000);
    long start = System.currentTimeMillis();
    for(int i=0;i<50000;i++){
      Thread thread = new Thread(new Runnable() {

        @Override
        public void run() {
          System.out.println("hello");
          count.countDown();
        }
      });
      thread.start();
    }

    while(count.getCount()!=0){//堵塞等待5w個線程運行完畢

    }
    long end = System.currentTimeMillis();
    System.out.println("50000個線程都執(zhí)行完了,共用時:"+(end-start)+"ms");


  }

使用線程池5w線程運行完大約為400ms,不使用線程池運行大約為4350ms左右,其效率可見一斑(讀者可以自行測試,不過由于電腦配置不一樣,跑出來的數(shù)據(jù)會有差別,但使用線程池絕對是比創(chuàng)建線程要快的)。

java如何使用線程池&#63;

上面的測試代碼中已經(jīng)使用了線程池,下面正式介紹一下。

java所有的線程池最頂層是一個Executor接口,其只有一個execute方法,用于執(zhí)行所有的任務(wù),java又提供了ExecutorService接口繼承自Executor并且擴充了一下方法,在往下就是AbstractExecutorService這個抽象類,其實現(xiàn)了ExecutorService,最后就是ThreadPoolExecutor其繼承自上面的抽象類,我們常使用的java線程池就是創(chuàng)建的這個類的實例。

而上面我們使用Executors是一個工具類,它就是一個語法糖,為我們把各種不同的業(yè)務(wù)的線程池參數(shù)進行封裝,進行new操作。

 public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                   0L, TimeUnit.MILLISECONDS,
                   new LinkedBlockingQueue<Runnable>());
  }

上面就是Executors.newFixedThreadPool(10)的源碼。

下面重點來了,說一說ThreadPoolExecutor構(gòu)造方法各參數(shù)的意思。

 public ThreadPoolExecutor(int corePoolSize,
               int maximumPoolSize,
               long keepAliveTime,
               TimeUnit unit,
               BlockingQueue<Runnable> workQueue,
               ThreadFactory threadFactory,
               RejectedExecutionHandler handler)

上面這個構(gòu)造方法是最全的。

下面我們根據(jù)源碼來解釋部分參數(shù)意思,這樣更有說服力。

下面是ThreadPoolExecutor#execute方法,就是我們上面接口調(diào)用的execute實際執(zhí)行者。

 public void execute(Runnable command) {
    if (command == null)
      throw new NullPointerException();

    int c = ctl.get();
    if (workerCountOf(c) < corePoolSize) {
      if (addWorker(command, true))
        return;
      c = ctl.get();
    }
    if (isRunning(c) && workQueue.offer(command)) {
      int recheck = ctl.get();
      if (! isRunning(recheck) && remove(command))
        reject(command);
      else if (workerCountOf(recheck) == 0)
        addWorker(null, false);
    }
    else if (!addWorker(command, false))
      reject(command);
  }

ctl是一個AtomicInteger實例,是一個提供了原子語句的CAS操作的類,它用來記錄線程池中當前運行的線程數(shù)量加上-2^29,workCountOf方法就取得其絕對值(可以去看源碼如何實現(xiàn)),當其小于corePoolSize時,會調(diào)用addWorker方法(是用來創(chuàng)建一個新Workder,Workder會創(chuàng)建一個Thread,所以就是創(chuàng)建線程的方法),addWorkd創(chuàng)建線程過程中會跟corePoolSize或者maxnumPoolSize的值比較(當傳入true會根corePoolSize比較,false會根據(jù)maxnumPoolSize比較,大于等于其值會創(chuàng)建失敗)??梢娙绾萎斍斑\行中的線程數(shù)量小于corePoolSize就是創(chuàng)建并且也會創(chuàng)建成功(
只簡單的討論線程池Running狀態(tài)下)。

如果當運行中線程數(shù)大于等于corePoolSize時,進入第二個if,isRunning是跟SHUTDOWN(其值=0)比較,之前說過c等于當前運行的線程數(shù)量加上-2^29,如果當前當前運行的線程數(shù)據(jù)達到2^29時其值就=0,isRunning返回false,else中在執(zhí)行addWorkd也會返回false(addWorkd也對其進行了檢驗),所以這表示線程池最多能支持2^29個線程同時運行(足夠用了)。

workQueue.offer(command)就是將runnable加入等待隊列,加入等待隊列后runWorker方法會從隊列中獲取任務(wù)執(zhí)行的。如果當前隊列采用的是有界隊列(ArrayBlockingQueue)當隊列滿了offer就會返回false,這是就進入else if,看!這里傳入了false,說明這里要跟maxnumPoolSize比較了,如果這里運行的線程數(shù)大于等于maxnumPoolSize,那么這個線程任務(wù)就要被線程池拒絕了,執(zhí)行reject(command),拒絕方法中使用了我們ThreadPoolExecutor構(gòu)造方法中的RejectedExecutionHandler(拒絕策略),后面再詳細解釋。

經(jīng)過上面的結(jié)合源碼的介紹,下面對們ThreadPoolExecutor的參數(shù)介紹就好理解了。

線程池中線程創(chuàng)建和拒絕策略

corePoolSize,maxnumPoolSize,BlockingQueue這三個要一塊說

當線程池運行的線程小于corePoolSize時,來一個新線程任務(wù)總是會新建一個線程來執(zhí)行;當大于corePoolSize就會把任務(wù)加入到等待隊列blockingQueue中,如果你傳入的BlockingQueue是一個無界隊列(LinkedBlockingQueue)這是隊列可以存放“無窮多”的任務(wù),所有總是會加入隊列成功,跟maxnumPoolSize就沒關(guān)系了,這也表示線程池中線程數(shù)最多為corePoolSize個;但是如果你傳入的是有界隊列(ArrayBlockingQueue,SynchronousQueue),當隊列滿時,并且線程數(shù)小于maxmunPoolSize就是創(chuàng)建新的線程直至線程數(shù)大于maxnumPoolSize;如果當線程數(shù)量大于maxnumPoolSize時,在加入任務(wù)就會被線程池拒絕。

RejectedExecutionHandler拒絕策略java給實現(xiàn)了4個AbortPolicy,CallerRunsPolicy,DiscardOldestPolicy,DiscardPolicy用戶也可以自己實現(xiàn)該接口實現(xiàn)自己的拒絕策略;第一個就是直接拋出異常,我們可以進行trycatch處理;第二個就是該新任務(wù)直接運行;第三個是取消隊列中最老的;第四個是取消當前任務(wù)。

關(guān)于Java中線程池的實現(xiàn)原理是什么就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

網(wǎng)站題目:Java中線程池的實現(xiàn)原理是什么
網(wǎng)址分享:http://www.rwnh.cn/article24/jdgeje.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供云服務(wù)器、全網(wǎng)營銷推廣、動態(tài)網(wǎng)站網(wǎng)站設(shè)計、搜索引擎優(yōu)化、軟件開發(fā)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都app開發(fā)公司
南华县| 凤冈县| 闸北区| 灵璧县| 明溪县| 麦盖提县| 马关县| 宣威市| 凌海市| 温宿县| 浮山县| 连州市| 乌鲁木齐市| 宁河县| 商丘市| 伊春市| 岑溪市| 隆安县| 米泉市| 望奎县| 新丰县| 田阳县| 广平县| 闽侯县| 铜梁县| 昌图县| 壶关县| 莆田市| 聊城市| 亳州市| 勐海县| 成安县| 安义县| 邢台市| 凯里市| 寿阳县| 抚宁县| 黔东| 文安县| 微博| 富平县|