<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      安卓筆記俠

      專注安卓開發

      導航

      JAVA線程池原理詳解一

      線程池的優點

      1、線程是稀缺資源,使用線程池可以減少創建和銷毀線程的次數,每個工作線程都可以重復使用。

      2、可以根據系統的承受能力,調整線程池中工作線程的數量,防止因為消耗過多內存導致服務器崩潰。

      線程池的創建

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

      corePoolSize:線程池核心線程數量

      maximumPoolSize:線程池最大線程數量

      keepAliverTime:當活躍線程數大于核心線程數時,空閑的多余線程最大存活時間

      unit:存活時間的單位

      workQueue:存放任務的隊列

      handler:超出線程范圍和隊列容量的任務的處理程序

      線程池的實現原理

        這里寫圖片描述

      提交一個任務到線程池中,線程池的處理流程如下:

      1、判斷線程池里的核心線程是否都在執行任務,如果不是(核心線程空閑或者還有核心線程沒有被創建)則創建一個新的工作線程來執行任務。如果核心線程都在執行任務,則進入下個流程。

      2、線程池判斷工作隊列是否已滿,如果工作隊列沒有滿,則將新提交的任務存儲在這個工作隊列里。如果工作隊列滿了,則進入下個流程。

      3、判斷線程池里的線程是否都處于工作狀態,如果沒有,則創建一個新的工作線程來執行任務。如果已經滿了,則交給飽和策略來處理這個任務。

      線程池的源碼解讀

      1、ThreadPoolExecutor的execute()方法

      public void execute(Runnable command) {
              if (command == null)
                  throw new NullPointerException();
             //如果線程數大于等于基本線程數或者線程創建失敗,將任務加入隊列
              if (poolSize >= corePoolSize || !addIfUnderCorePoolSize(command)) {
                //線程池處于運行狀態并且加入隊列成功
                  if (runState == RUNNING && workQueue.offer(command)) {
                      if (runState != RUNNING || poolSize == 0)
                          ensureQueuedTaskHandled(command);
                  }
               //線程池不處于運行狀態或者加入隊列失敗,則創建線程(創建的是非核心線程)
                  else if (!addIfUnderMaximumPoolSize(command))
                 //創建線程失敗,則采取阻塞處理的方式
                      reject(command); // is shutdown or saturated
              }
          }
      

      2、創建線程的方法:addIfUnderCorePoolSize(command)

      private boolean addIfUnderCorePoolSize(Runnable firstTask) {
              Thread t = null;
              final ReentrantLock mainLock = this.mainLock;
              mainLock.lock();
              try {
                  if (poolSize < corePoolSize && runState == RUNNING)
                      t = addThread(firstTask);
              } finally {
                  mainLock.unlock();
              }
              if (t == null)
                  return false;
              t.start();
              return true;
          }
      

      我們重點來看第7行:

      private Thread addThread(Runnable firstTask) {
              Worker w = new Worker(firstTask);
              Thread t = threadFactory.newThread(w);
              if (t != null) {
                  w.thread = t;
                  workers.add(w);
                  int nt = ++poolSize;
                  if (nt > largestPoolSize)
                      largestPoolSize = nt;
              }
              return t;
          }
      

      這里將線程封裝成工作線程worker,并放入工作線程組里,worker類的方法run方法:

      public void run() {
                  try {
                      Runnable task = firstTask;
                      firstTask = null;
                      while (task != null || (task = getTask()) != null) {
                          runTask(task);
                          task = null;
                      }
                  } finally {
                      workerDone(this);
                  }
              }
      

      worker在執行完任務后,還會通過getTask方法循環獲取工作隊里里的任務來執行。

      我們通過一個程序來觀察線程池的工作原理:

      1、創建一個線程

      public class ThreadPoolTest implements Runnable
      {
          @Override
          public void run()
          {
              try
              {
                  Thread.sleep(300);
              }
              catch (InterruptedException e)
              {
                  e.printStackTrace();
              }
          }
      }
      

      2、線程池循環運行16個線程:

      public static void main(String[] args)
          {
              LinkedBlockingQueue<Runnable> queue =
                  new LinkedBlockingQueue<Runnable>(5);
              ThreadPoolExecutor threadPool = new ThreadPoolExecutor(5, 10, 60, TimeUnit.SECONDS, queue);
              for (int i = 0; i < 16 ; i++)
              {
                  threadPool.execute(
                      new Thread(new ThreadPoolTest(), "Thread".concat(i + "")));
                  System.out.println("線程池中活躍的線程數: " + threadPool.getPoolSize());
                  if (queue.size() > 0)
                  {
                      System.out.println("----------------隊列中阻塞的線程數" + queue.size());
                  }
              }
              threadPool.shutdown();
          }
      

      執行結果:

      線程池中活躍的線程數: 1
      線程池中活躍的線程數: 2
      線程池中活躍的線程數: 3
      線程池中活躍的線程數: 4
      線程池中活躍的線程數: 5
      線程池中活躍的線程數: 5
      ----------------隊列中阻塞的線程數1
      線程池中活躍的線程數: 5
      ----------------隊列中阻塞的線程數2
      線程池中活躍的線程數: 5
      ----------------隊列中阻塞的線程數3
      線程池中活躍的線程數: 5
      ----------------隊列中阻塞的線程數4
      線程池中活躍的線程數: 5
      ----------------隊列中阻塞的線程數5
      線程池中活躍的線程數: 6
      ----------------隊列中阻塞的線程數5
      線程池中活躍的線程數: 7
      ----------------隊列中阻塞的線程數5
      線程池中活躍的線程數: 8
      ----------------隊列中阻塞的線程數5
      線程池中活躍的線程數: 9
      ----------------隊列中阻塞的線程數5
      線程池中活躍的線程數: 10
      ----------------隊列中阻塞的線程數5
      Exception in thread "main" java.util.concurrent.RejectedExecutionException: Task Thread[Thread15,5,main] rejected from java.util.concurrent.ThreadPoolExecutor@232204a1[Running, pool size = 10, active threads = 10, queued tasks = 5, completed tasks = 0]
          at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2047)
          at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:823)
          at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1369)
          at test.ThreadTest.main(ThreadTest.java:17)
      

      從結果可以觀察出:

      1、創建的線程池具體配置為:核心線程數量為5個;全部線程數量為10個;工作隊列的長度為5。

      2、我們通過queue.size()的方法來獲取工作隊列中的任務數。

      3、運行原理:

            剛開始都是在創建新的線程,達到核心線程數量5個后,新的任務進來后不再創建新的線程,而是將任務加入工作隊列,任務隊列到達上線5個后,新的任務又會創建新的普通線程,直到達到線程池最大的線程數量10個,后面的任務則根據配置的飽和策略來處理。我們這里沒有具體配置,使用的是默認的配置AbortPolicy:直接拋出異常。

        當然,為了達到我需要的效果,上述線程處理的任務都是利用休眠導致線程沒有釋放!!!

      RejectedExecutionHandler:飽和策略

      當隊列和線程池都滿了,說明線程池處于飽和狀態,那么必須對新提交的任務采用一種特殊的策略來進行處理。這個策略默認配置是AbortPolicy,表示無法處理新的任務而拋出異常。JAVA提供了4中策略:

      1、AbortPolicy:直接拋出異常

      2、CallerRunsPolicy:只用調用所在的線程運行任務

      3、DiscardOldestPolicy:丟棄隊列里最近的一個任務,并執行當前任務。

      4、DiscardPolicy:不處理,丟棄掉。

      我們現在用第四種策略來處理上面的程序:

      public static void main(String[] args)
          {
              LinkedBlockingQueue<Runnable> queue =
                  new LinkedBlockingQueue<Runnable>(3);
              RejectedExecutionHandler handler = new ThreadPoolExecutor.DiscardPolicy();
      
              ThreadPoolExecutor threadPool = new ThreadPoolExecutor(2, 5, 60, TimeUnit.SECONDS, queue,handler);
              for (int i = 0; i < 9 ; i++)
              {
                  threadPool.execute(
                      new Thread(new ThreadPoolTest(), "Thread".concat(i + "")));
                  System.out.println("線程池中活躍的線程數: " + threadPool.getPoolSize());
                  if (queue.size() > 0)
                  {
                      System.out.println("----------------隊列中阻塞的線程數" + queue.size());
                  }
              }
              threadPool.shutdown();
          }  

      結果

      線程池中活躍的線程數: 1
      線程池中活躍的線程數: 2
      線程池中活躍的線程數: 2
      ----------------隊列中阻塞的線程數1
      線程池中活躍的線程數: 2
      ----------------隊列中阻塞的線程數2
      線程池中活躍的線程數: 2
      ----------------隊列中阻塞的線程數3
      線程池中活躍的線程數: 3
      ----------------隊列中阻塞的線程數3
      線程池中活躍的線程數: 4
      ----------------隊列中阻塞的線程數3
      線程池中活躍的線程數: 5
      ----------------隊列中阻塞的線程數3
      線程池中活躍的線程數: 5
      ----------------隊列中阻塞的線程數3
      

      這里采用了丟棄策略后,就沒有再拋出異常,而是直接丟棄。在某些重要的場景下,可以采用記錄日志或者存儲到數據庫中,而不應該直接丟棄。  

       

      posted on 2018-06-29 19:37  安卓筆記俠  閱讀(744)  評論(0)    收藏  舉報

      主站蜘蛛池模板: 丝袜美腿一区二区三区| 日本少妇xxx做受| 久久精品国产精品亚洲综合| 国产盗摄xxxx视频xxxx | 久久亚洲人成网站| 亚洲精品一二三四区| 又湿又紧又大又爽A视频男| 丁香婷婷激情综合俺也去| 成人国产乱对白在线观看| 亚洲成A人片在线观看的电影| 兖州市| 在线成人| 国产精品综合在线免费看| 国产午夜精品久久精品电影| 天天做日日做天天添天天欢公交车| 神马午夜久久精品人妻| 亚洲粉嫩av一区二区黑人| 日日摸天天爽天天爽视频| 亚洲中文字幕一区精品自| 蜜臀av久久国产午夜| 国产日韩一区二区在线| 中文字幕va一区二区三区| 亚洲乱理伦片在线观看中字| 国产美女69视频免费观看| 国精品无码一区二区三区在线蜜臀| 亚洲精品综合一区二区三区| 中文字幕久久国产精品| 久久月本道色综合久久| 亚洲国产女性内射第一区| 性欧美乱熟妇xxxx白浆| 人人做人人澡人人人爽| 特级毛片在线大全免费播放| 在线播放国产精品一品道| 国产99视频精品免费视频36| 精品国产免费人成在线观看| 高潮射精日本韩国在线播放| 韩国午夜福利片在线观看| 国产 一区二区三区视频| 舞阳县| 中文字幕av国产精品| 金阳县|