日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java线性池的使用方式以及核心运行原理

發布時間:2025/5/22 java 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java线性池的使用方式以及核心运行原理 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Java線性池的使用方式以及核心運行原理

  • 一、為什么需要線性池?
  • 二、線性池的處理流程
  • 三、線程池的使用(ThreadPoolExecutor)
  • 四、線程池的注意事項

一、為什么需要線性池?

java為了提高并發度,可以使用多線程共同執行,但是如果有大量的線程在短時間被創建或者銷毀,就會占用大量的系統時間,影響系統效率。

有了線性池以后,線程創建后在指定的時間內統一歸系統管理,而不是在執行時創建,執行完銷毀。從而避免了系統頻繁創建、銷毀線程而帶來的系統開銷。

二、線性池的處理流程


1.先判斷核心線程池里的核心線程們是否空閑,如果空閑就把這個新的任務給空閑的核心線程執行,如果沒有空閑并且核心線程數小于corePoolSize,則創建新的核心線程去執行這個任務。
2.如果線程池的線程數已達到核心線程數,并且這些線程都繁忙,則把這個新的任務放到等待隊列中去。如果等待隊列已經滿了,則判斷線程數是否達到maximumPoolSize,如果沒達到,則創建新的線程執行任務。
3.如果到達了,則交給RejectedExecutionHandler(拒絕策略)來決定如何處理這個新的任務。

三、線程池的使用(ThreadPoolExecutor)

在java里,線程池的概念就是Executor這個接口,具體實現是ThreadPoolExecutor類,這個類是線性池中最核心的一個類,如果要透徹了解線性池,就必須先了解這個類。

ThreadPoolExecutor繼承了AbstractExecutorService類,并提供了四個構造器:

Constructor 描述 ThreadPoolExecutor?(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) 創建一個新的 ThreadPoolExecutor與給定的初始參數和默認線程工廠和拒絕的執行處理程序。 ThreadPoolExecutor?(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler) 創建一個新的 ThreadPoolExecutor與給定的初始參數和默認線程工廠。 ThreadPoolExecutor?(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) 使用給定的初始參數和默認拒絕的執行處理程序創建一個新的 ThreadPoolExecutor 。 ThreadPoolExecutor?(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) 用給定的初始參數創建一個新的 ThreadPoolExecutor 。

ThreadPoolExecutor繼承了AbstractExecutorService類,并提供了四個構造器,事實上,通過觀察每個構造器的源碼具體實現,發現前面三個構造器都是調用的第四個構造器進行的初始化工作。
下面解釋下一下構造器中各個參數的含義:
1.corePoolSize(線程池的基本大小)

當提交一個任務到線程池時,線程池會創建一個線程來執行任務,即使其他空閑的基本線程能夠執行新任務也會創建線程,等到需要執行的任務數大于線程池基本大小時就不再創建。如果調用了線程池的prestartAllCoreThreads方法,線程池會提前創建并啟動所有基本線程。

2.runnableTaskQueue(任務隊列)

用于保存等待執行的任務的阻塞隊列。可以選擇以下幾個阻塞隊列。

  • ArrayBlockingQueue:是一個基于數組結構的有界阻塞隊列,此隊列按 FIFO(先進先出)原則對元素進行排序。

  • LinkedBlockingQueue:一個基于鏈表結構的阻塞隊列,此隊列按FIFO (先進先出) 排序元素,吞吐量通常要高于ArrayBlockingQueue。

  • SynchronousQueue:一個不存儲元素的阻塞隊列。每個插入操作必須等到另一個線程調用移除操作,否則插入操作一直處于阻塞狀態,吞吐量通常要高于LinkedBlockingQueue。

  • PriorityBlockingQueue:一個具有優先級得無限阻塞隊列。

3.maximumPoolSize(線程池最大大小)

線程池允許創建的最大線程數。如果隊列滿了,并且已創建的線程數小于最大線程數,則線程池會再創建新的線程執行任務。值得注意的是如果使用了無界的任務隊列這個參數就沒什么效果。


4.ThreadFactory:用于設置創建線程的工廠

可以通過線程工廠給每個創建出來的線程設置更有意義的名字,Debug和定位問題時非常又幫助。

5.RejectedExecutionHandler(飽和策略)

當隊列和線程池都滿了,說明線程池處于飽和狀態,那么必須采取一種策略處理提交的新任務。這個策略默認情況下是AbortPolicy,表示無法處理新任務時拋出異常。以下是JDK1.5提供的四種策略。

  • AbortPolicy:直接拋出異常。
  • CallerRunsPolicy:只用調用者所在線程來運行任務。
  • DiscardOldestPolicy:丟棄隊列里最近的一個任務,并執行當前任務。
  • DiscardPolicy:不處理,丟棄掉。.
  • 當然也可以根據應用場景需要來實現RejectedExecutionHandler接口自定義策略。如記錄日志或持久化不能處理的任務。

6.keepAliveTime(線程活動保持時間)

線程池的工作線程空閑后,保持存活的時間。所以如果任務很多,并且每個任務執行的時間比較短,可以調大這個時間,提高線程的利用率。

7.TimeUnit(線程活動保持時間的單位)

可選的單位有天(DAYS),小時(HOURS),分鐘(MINUTES),毫秒(MILLISECONDS),微秒(MICROSECONDS, 千分之一毫秒)和毫微秒(NANOSECONDS, 千分之一微秒)。

四、線程池的注意事項

雖然線程池能大大提高服務器的并發性能,但使用它也會存在一定風險。與所有多線程應用程序一樣,用線程池構建的應用程序容易產生各種并發問題,如對共享資源的競爭和死鎖。此外,如果線程池本身的實現不健壯,或者沒有合理地使用線程池,還容易導致與線程池有關的死鎖、系統資源不足和線程泄漏等問題。
1) 建議使用new ThreadPoolExecutor(…)的方式創建線程池

線程池的創建不應使用Executors 去創建,而應該通過 ThreadPoolExecutor創建,這樣可以讓讀者更加明確地知道線程池的參數設置、運行規則,規避資源耗盡的風險,這一點在也阿里巴巴JAVA開發手冊中也有明確要求。這一點不容小覷,曾有同學因為線程池使用不當導致生產的同一臺機器上部署的多個應用都因無法創建線程池而出現故障。

2) 合理設置線程數

①CPU密集型:

定義:CPU密集型的意思就是該任務需要大量運算,而沒有阻塞,CPU一直全速運行。
CPU密集型任務只有在真正的多核CPU上才可能得到加速(通過多線程)。
CPU密集型任務配置盡可能少的線程數。
CPU密集型線程數配置公式:(CPU核數+1)個線程的線程池

②IO密集型:

定義:IO密集型,即該任務需要大量的IO,即大量的阻塞。
在單線程上運行IO密集型任務會導致浪費大量的CPU運算能力浪費在等待。
所以IO密集型任務中使用多線程可以大大的加速程序運行,即使在單核CPU上,這種加速主要利用了被浪費掉的阻塞時間。

- 第一種配置方式:
由于IO密集型任務線程并不是一直在執行任務,則應配置盡可能多的線程。
配置公式:CPU核數 * 2。

- 第二種配置方式:
IO密集型時,大部分線程都阻塞,故需要多配置線程數。
配置公式:CPU核數 / (1 – 阻塞系數)(0.8~0.9之間)
比如:8核 / (1 – 0.9) = 80個線程數(10倍)

3) 設置能代表具體業務的線程名稱

這樣方便通過日志的線程名稱識別所屬業務。具體實現可以通過指定ThreadPoolExecutor的ThreadFactory參數,如使Spring提供的CustomizableThreadFactory

總結

以上是生活随笔為你收集整理的Java线性池的使用方式以及核心运行原理的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。