摘要:每個通過網絡到達服務器的連接都被包裝成一個任務并且傳遞給線程池。線程池的線程會并發的處理連接上的請求。用線程池控制線程數量,其他線程排隊等候。實現包,線程池頂級接口是但是嚴格意義講并不是一個線程。此線程池支持定時以及周期性執行任務的需求。
tutorial site1
tutorial site2
每啟動一個新線程都會有相應的性能開銷(涉及到OS的交互:創建線程,銷毀線程),而且每個線程都需要給棧分配一些內存等等。這種代價隨著新線程不斷的創建,將會大大降低性能甚至使JVM崩潰。
如何解決?
使線程可以復用,執行完一個任務,并不被銷毀,而是可以繼續執行其他的任務。這樣避免了創建以及銷毀線程的代價以及線程過多造成內存消耗過度以及切換過度問題。
線程池(Thread Pool)的引入就是:限制應用程序中同一時刻運行的線程數。根據系統的環境,可以手動或者自動設置線程數量,達到最佳效果。
可以把并發執行的任務傳遞給一個線程池,來替代為每個并發執行的任務都啟動一個新的線程。只要池里有空閑的線程,任務就會分配給一個線程執行。 在線程池的內部,任務被插入一個阻塞隊列(任務隊列), 線程池的線程會去取這個隊列的任務。當一個新任務插入隊列時,一個空閑線程就會成功的從隊列中取出任務并執行它。
線程池經常應用在多線程服務器上。每個通過網絡到達服務器的連接都被包裝成一個任務并且傳遞給線程池。線程池的線程會并發的處理連接上的請求。Java 5 在 java.util.concurrent 包中自帶了內置的線程池,所以你不用非得實現自己的線程池。
好處線程池的作用:
合理利用線程池能夠帶來三個好處。
第一:降低資源消耗。通過重復利用已創建的線程降低線程創建和銷毀造成的消耗。
第二:提高響應速度。當任務到達時,任務可以不需要等到線程創建就能立即執行。
第三:提高線程的可管理性。線程是稀缺資源,如果無限制的創建,不僅會消耗系統資源,還會降低系統的穩定性,使用線程池可以進行統一的分配,調優和監控。但是要做到合理的利用線程池,必須對其原理了如指掌。
線程池實現了系統中線程的數量。
根據系統的環境情況,可以自動或手動設置線程數量,達到運行的最佳效果;少了浪費了系統資源,多了造成系統擁擠效率不高。用線程池控制線程數量,其他線程排隊等候。一個任務執行完畢,再從隊列的中取最前面的任務開始執行。若隊列中沒有等待進程,線程池的這一資源處于等待。當一個新任務需要運行時,如果線程池中有等待的工作線程,就可以開始運行了;否則進入等待隊列。
JUC 包,線程池頂級接口是Executor. 但是嚴格意義講Executor并不是一個線程。 而只是一個執行線程的工具。真正的線程池的接口是ExecutorService.
ExecutorService | 真正的線程池的接口 |
---|---|
ScheduledExecutorService | 能和Timer/TimerTask類似,解決那些需要任務重復執行的問題 |
ThreadPoolExecutor | ExecutorService的默認實現 |
ScheduledThreadPoolExecutor | 繼承 ThreadPoolExecutor 的 ScheduledExecutorService 接口實現,周期性任務調度的類實現 |
要配置一個線程池是比較復雜的,尤其是對于線程池的原理不是很清楚的情況下,很有可能配置的線程池不是較優的,因此在 Executors 類里面提供了一些靜態工廠,生成一些常用的線程池。
1. newSingleThreadExecutor()
創建一個單線程的線程池。這個線程池只有一個線程在工作,也就是相當于單線程串行執行所有任務。如果這個唯一的線程因為異常結束,那么會有一個新的線程來替代它。此線程池保證所有任務的執行順序按照任務的提交順序執行。
javapublic classMyThread extends Thread { publicvoid run() { System.out.println(Thread.currentThread().getName() + " 正在執行。。。"); } } public classTestSingleThreadExecutor { public static void main(String[] args) { // 創建一個可重用固定線程數的線程池 ExecutorService pool = Executors.newSingleThreadExecutor(); // 創建實現了 Runnable 接口對象,Thread 對象當然也實現了 Runnable 接口 Thread t1 = new MyThread(); Thread t2 = new MyThread(); Thread t3 = new MyThread(); Thread t4 = new MyThread(); Thread t5 = new MyThread(); // 將線程放入池中進行執行 pool.execute(t1); pool.execute(t2); pool.execute(t3); pool.execute(t4); pool.execute(t5); // 關閉線程池 pool.shutdown(); } }
2.newFixedThreadPool()
創建固定大小的線程池。每次提交一個任務就創建一個線程,直到線程達到線程池的最大大小。線程池的大小一旦達到最大值就會保持不變,如果某個線程因為執行異常而結束,那么線程池會補充一個新線程。
javapublicclass TestFixedThreadPool { publicstaticvoid main(String[] args) { // 創建一個可重用固定線程數的線程池 ExecutorService pool = Executors.newFixedThreadPool(2); // 創建實現了 Runnable 接口對象,Thread 對象當然也實現了 Runnable 接口 Thread t1 = new MyThread(); Thread t2 = new MyThread(); Thread t3 = new MyThread(); Thread t4 = new MyThread(); Thread t5 = new MyThread(); // 將線程放入池中進行執行 pool.execute(t1); pool.execute(t2); pool.execute(t3); pool.execute(t4); pool.execute(t5); // 關閉線程池 pool.shutdown(); } }
newCachedThreadPool
創建一個可緩存的線程池。如果線程池的大小超過了處理任務所需要的線程,
那么就會回收部分空閑(60 秒不執行任務)的線程,當任務數增加時,此線程池又可以智能的添加新線程來處理任務。此線程池不會對線程池大小做限制,線程池大小完全依賴于操作系統(或者說 JVM)能夠創建的最大線程大小。
javapublicclass TestCachedThreadPool { publicstaticvoid main(String[] args) { // 創建一個可重用固定線程數的線程池 ExecutorService pool = Executors.newCachedThreadPool(); // 創建實現了 Runnable 接口對象,Thread 對象當然也實現了 Runnable 接口 Thread t1 = new MyThread(); Thread t2 = new MyThread(); Thread t3 = new MyThread(); Thread t4 = new MyThread(); Thread t5 = new MyThread(); // 將線程放入池中進行執行 pool.execute(t1); pool.execute(t2); pool.execute(t3); pool.execute(t4); pool.execute(t5); // 關閉線程池 pool.shutdown(); } }
4.newScheduledThreadPool
創建一個大小無限的線程池。此線程池支持定時以及周期性執行任務的需求。
javapublicclass TestScheduledThreadPoolExecutor { publicstaticvoid main(String[] args) { ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(1); exec.scheduleAtFixedRate(new Runnable() {// 每隔一段時間就觸發異常 @Override publicvoid run() { //throw new RuntimeException(); System.out.println("================"); } }, 1000, 5000, TimeUnit.MILLISECONDS); exec.scheduleAtFixedRate(new Runnable() {// 每隔一段時間打印系統時間,證明兩者是互不影響的 @Override publicvoid run() { System.out.println(System.nanoTime()); } }, 1000, 2000, TimeUnit.MILLISECONDS); } }
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/64364.html
摘要:導語本文章匯總了本人在學習基礎之緒論篇數據結構篇函數篇面向對象篇控制流程篇和元編程篇學習筆記的鏈接,打算入門的朋友們可以按需查看并交流。 導語:本文章匯總了本人在學習Python基礎之緒論篇、數據結構篇、函數篇、面向對象篇、控制流程篇和元編程篇學習筆記的鏈接,打算入門Python的朋友們可以按需查看并交流。 第一部分:緒論篇 1、Python數據模型 第二部分:數據結構篇 2、序列構成...
摘要:基礎問題的的性能及原理之區別詳解備忘筆記深入理解流水線抽象關鍵字修飾符知識點總結必看篇中的關鍵字解析回調機制解讀抽象類與三大特征時間和時間戳的相互轉換為什么要使用內部類對象鎖和類鎖的區別,,優缺點及比較提高篇八詳解內部類單例模式和 Java基礎問題 String的+的性能及原理 java之yield(),sleep(),wait()區別詳解-備忘筆記 深入理解Java Stream流水...
摘要:基礎問題的的性能及原理之區別詳解備忘筆記深入理解流水線抽象關鍵字修飾符知識點總結必看篇中的關鍵字解析回調機制解讀抽象類與三大特征時間和時間戳的相互轉換為什么要使用內部類對象鎖和類鎖的區別,,優缺點及比較提高篇八詳解內部類單例模式和 Java基礎問題 String的+的性能及原理 java之yield(),sleep(),wait()區別詳解-備忘筆記 深入理解Java Stream流水...
摘要:基礎問題的的性能及原理之區別詳解備忘筆記深入理解流水線抽象關鍵字修飾符知識點總結必看篇中的關鍵字解析回調機制解讀抽象類與三大特征時間和時間戳的相互轉換為什么要使用內部類對象鎖和類鎖的區別,,優缺點及比較提高篇八詳解內部類單例模式和 Java基礎問題 String的+的性能及原理 java之yield(),sleep(),wait()區別詳解-備忘筆記 深入理解Java Stream流水...
閱讀 3581·2023-04-26 02:55
閱讀 2849·2021-11-02 14:38
閱讀 4135·2021-10-21 09:39
閱讀 2842·2021-09-27 13:36
閱讀 3943·2021-09-22 15:08
閱讀 2643·2021-09-08 10:42
閱讀 2802·2019-08-29 12:21
閱讀 667·2019-08-29 11:22