<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                ## **什么是線程池?** 線程池可以理解為執行特點數量線程的管理容器 ## **線程池作用** * **降低資源消耗** 通過重復利用已創建的線程降低線程創建和銷毀造成的消耗。 * **提高響應速度** 當任務到達時,任務可以不需要等到線程創建就能立即執行。 * **提高線程的可管理性** 使用線程池可以進行統一分配、調優和監控 ## **線程池的創建方式** Java通過Executors(jdk1.5并發包)提供四種線程池 * newCachedThreadPool 創建一個相對無限大可緩存線程池,如果線程池長度超過處理需要,可靈活回收空閑線程,若無可回收,則新建線程 ``` ExecutorService newCachedThreadPool = Executors.newCachedThreadPool(); for (int i = 0; i < 10; i++) { final int temp = i; newCachedThreadPool.execute(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName() + ",i:" + temp); } }); } ``` 源碼分析 ``` public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(), threadFactory); } ``` newCachedThreadPool方法只是對ThreadPoolExecutor方法做了簡單的封裝,其中 1.corePoolSize:核心線程數為0 2.maximumPoolSize:最大線程數為最大整數值Integer.MAX\_VALUE,可以理解為無限大 3.keepAliveTime:空閑等待銷毀時間為60S 4.workQueue:線程緩存隊列采用的是SynchronousQueue單元素阻塞隊列 總結:核心線程數小于最大線程數且為0,所以任務完成后60S所有線程都會銷毀,因為采用的是SynchronousQueue單元素阻塞隊列,隊列無法緩存多個任務,所以多任務時會不停的創建線程。 * newFixedThreadPool 創建一個固定長度的線程池,可控制線程最大并發數,超出的線程會在隊列中等待 ``` ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(3); for (int i = 0; i < 10; i++) { final int temp = i; newFixedThreadPool.execute(new Runnable() { @Override public void run() { ... Thread.sleep(100); ... System.out.println(Thread.currentThread().getName() + ",i:" + temp); } }); } ``` 執行結果如下、并且程序不會退出 ``` pool-1-thread-1,i:0 pool-1-thread-2,i:1 pool-1-thread-3,i:2 pool-1-thread-1,i:3 pool-1-thread-2,i:4 pool-1-thread-3,i:5 pool-1-thread-1,i:6 pool-1-thread-2,i:7 pool-1-thread-3,i:8 pool-1-thread-1,i:9 ``` 源碼分析 ``` public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); } ``` newFixedThreadPool方法也只是對ThreadPoolExecutor方法做了簡單的封裝,其中 1.corePoolSize:核心線程數為用戶設定的值 2.maximumPoolSize:最大線程數為等于核心線程數 3.keepAliveTime:空閑等待銷毀時間為0S 4.workQueue:線程緩存隊列采用的是LinkedBlockingQueue隊列 總結:核心線程數等于最大線程數、所以線程池在創建三個線程后會一直維持,等待的任務保存在LinkedBlockingQueue隊列中,任務完成后線程池維持3個線程等待任務,剩余其他線程銷毀。 * newScheduledThreadPool 創建一個定長線程池,支持定時及周期性任務執行 ``` ScheduledExecutorService newScheduledThreadPool = Executors.newScheduledThreadPool(3); for (int i = 0; i < 10; i++) { final int temp = i; newScheduledThreadPool.schedule(new Runnable() { @Override public void run() { ... Thread.sleep(100); ... System.out.println(Thread.currentThread().getName() + ",i:" + temp); } }, 3, TimeUnit.SECONDS); } ``` 表示延遲3秒處理 源碼分析 ``` public class ScheduledThreadPoolExecutor extends ThreadPoolExecutor implements ScheduledExecutorService { ... public ScheduledThreadPoolExecutor(int corePoolSize) { super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue()); ... } ``` ScheduledThreadPoolExecutor也是繼承ThreadPoolExecutor了方法,其中 1.corePoolSize:核心線程數為用戶設定的值 2.maximumPoolSize:最大線程數為最大整數值Integer.MAX\_VALUE,可以理解為無限大 3.keepAliveTime:空閑等待銷毀時間為0S 4.workQueue:線程緩存隊列采用的是專門的DelayedWorkQueue隊列 總結:線程可無限創建,但是當任務數量小于核心線程數時,多余的線程都會第一時間被銷毀,只保留核心線程數量值的線程。 * newSingleThreadExecutor 創建一個單線程化的線程池,它只會用唯一的工作線程來執行任務,保證所有任務按照指定順序(FIFO, LIFO, 優先級)執行 ``` ExecutorService newSingleThreadExecutor = Executors.newSingleThreadExecutor(); for (int i = 0; i < 10; i++) { final int temp = i; newSingleThreadExecutor.execute(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName() + ",i:" + temp); } }); } ``` 源碼分析 ``` public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())); } ``` 底層使用的還是ThreadPoolExecutor的構造方法,其中 1.corePoolSize:核心線程數為1 2.maximumPoolSize:最大線程數為1 3.keepAliveTime:空閑等待銷毀時間為0S 4.workQueue:緩存隊列采用的是LinkedBlockingQueue隊列 總結:只創建并且保持一個線程在執行任務,所有等待任務保存在LinkedBlockingQueue隊列中 總結上面4中創建線程池的方法,似乎發現最終執行的還是ThreadPoolExecutor的構造方法,只是構造參數不同而已 * corePoolSize 核心池的大小。 當有任務來之后,就會創建一個線程去執行任務,當線程池中的線程數目達到corePoolSize后,就會把到達的任務放到緩存隊列當中 * maximumPoolSize 線程池最大線程數,它表示在線程池中最多能創建多少個線程 * keepAliveTime 最大連接數大于核心線程數時,空閑等待的線程待銷毀的時間 * workQueue 緩存隊列,線程池中線程數量大于核心線程數時,任務存入次隊列中 ## **線程池原理分析** 線程池的處理流程 ![](https://img.kancloud.cn/79/86/79868da81af0c67d5a4347d933c14352_776x452.jpg) ## **自定義線程池** 創建線程任務 ``` class TaskThread implements Runnable { private String name; public TaskThread(String name) { this.name = name; } @Override public void run() { System.out.println(Thread.currentThread().getName() + name); } } ``` 自定義線程池 ``` class test { public static void main(String[] args) { ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 2, 60L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(5)); for (int i = 0; i < 10; i++) { executor.execute(new TaskThread("任務" + i)); } executor.shutdown(); } } ``` 自定義線程中 1.corePoolSize:核心線程數為1 2.maximumPoolSize:最大線程數為2 3.keepAliveTime:空閑等待銷毀時間為60S 4.workQueue:緩存隊列采用的是ArrayBlockingQueue長度為5的有界隊列 執行結果 ``` java.util.concurrent.RejectedExecutionException... pool-1-thread-2任務6 pool-1-thread-2任務1 pool-1-thread-2任務2 pool-1-thread-2任務3 pool-1-thread-2任務4 pool-1-thread-2任務5 pool-1-thread-1任務0 ``` 最終執行了7次的任務,最后拋出RejectedExecutionException異常警告,那就來分析一下原因吧。 根據線程池的執行流程可分析 1.核心線程數為1,線程池會創建一個線程執行一個任務任務 2.當任務數量大于核心線程數量時,線程池會將未被分配執行的任務保存待緩存隊列中,因為緩存隊列是初始化長度為5的有界隊列,所有只能緩存5個任務。 3.緩存隊列存儲滿了之后,線程池判斷最大線程數,發現最大線程數為2,因為當前只創建了1個線程,所有線程池會再去創建一個線程去執行一個任務。 4.到最后線程池發現最大的線程數已經滿了,但是還是有任務需要執行,于似乎直接拒絕處理拋出異常。 ## **合理配置線程池** 需要根據任務的特性來分析 1. 任務的性質:CPU密集型、IO密集型和混雜型 2. 任務的優先級:高中低 3. 任務執行的時間:長中短 4. 任務的依賴性:是否依賴數據庫或者其他系統資源 * CPU密集型任務應配置盡可能小的線程,如配置CPU個數+1的線程數 * IO密集型任務應配置盡可能多的線程,因為IO操作不占用CPU,不要讓CPU閑下來,應加大線程數量,如配置兩倍CPU個數+1 * 混合型的任務,如果可以拆分,拆分成IO密集型和CPU密集型分別處理,前提是兩者運行的時間是差不多的,如果處理時間相差很大,則沒必要拆分了 * 前人總結的 最佳線程數=((線程等待時間+線程CPU時間)/線程CPU時間 )\* CPU數目
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看