如何在Java中实现线程池
線(xiàn)程是獨(dú)立程序的執(zhí)行路徑。 在java中,每個(gè)線(xiàn)程都擴(kuò)展java.lang.Thread類(lèi)或?qū)崿F(xiàn)java.lang.Runnable。
多線(xiàn)程是指在一個(gè)任務(wù)中同時(shí)執(zhí)行兩個(gè)或多個(gè)線(xiàn)程。在多線(xiàn)程中,每個(gè)任務(wù)可以具有多個(gè)線(xiàn)程,并且這些線(xiàn)程可以異步或同步地并行運(yùn)行。 您可以在我在此處撰寫(xiě)的有關(guān)多線(xiàn)程的另一教程中找到有關(guān)線(xiàn)程和多線(xiàn)程的更多信息。
1.什么是線(xiàn)程池
線(xiàn)程池代表一組執(zhí)行任務(wù)的工作線(xiàn)程,每個(gè)線(xiàn)程可以多次重用。 如果在所有線(xiàn)程都處于活動(dòng)狀態(tài)時(shí)提交了新任務(wù),則它們將在隊(duì)列中等待直到線(xiàn)程可用。 線(xiàn)程池實(shí)現(xiàn)在內(nèi)部使用LinkedBlockingQueue在隊(duì)列中添加和刪除任務(wù)。 我們通常想要的是一個(gè)工作隊(duì)列,該隊(duì)列與一組固定的工作線(xiàn)程組合在一起,該工作線(xiàn)程使用wait()和notify()來(lái)向等待線(xiàn)程發(fā)出新工作到達(dá)的信號(hào)。 以下示例顯示了一個(gè)簡(jiǎn)單的工作隊(duì)列,該隊(duì)列是Runnable對(duì)象的隊(duì)列。 盡管沒(méi)有特別要求Thread API使用Runnable接口,但這是調(diào)度程序和工作隊(duì)列的常用約定。 package tutorials;import java.util.concurrent.LinkedBlockingQueue;public class ThreadPool {private final int nThreads;private final PoolWorker[] threads;private final LinkedBlockingQueue queue;public ThreadPool(int nThreads) {this.nThreads = nThreads;queue = new LinkedBlockingQueue();threads = new PoolWorker[nThreads];for (int i = 0; i < nThreads; i++) {threads[i] = new PoolWorker();threads[i].start();}}public void execute(Runnable task) {synchronized (queue) {queue.add(task);queue.notify();}}private class PoolWorker extends Thread {public void run() {Runnable task;while (true) {synchronized (queue) {while (queue.isEmpty()) {try {queue.wait();} catch (InterruptedException e) {System.out.println("An error occurred while queue is waiting: " + e.getMessage());}}task = queue.poll();}// If we don't catch RuntimeException,// the pool could leak threadstry {task.run();} catch (RuntimeException e) {System.out.println("Thread pool is interrupted due to an issue: " + e.getMessage());}}}} }在處理隊(duì)列時(shí),使用同步塊很重要,以控制線(xiàn)程對(duì)隊(duì)列的訪(fǎng)問(wèn)。
package tutorials;public class Task implements Runnable {private int num;public Task(int n) {num = n;}public void run() {System.out.println("Task " + num + " is running.");} }import tutorials.Task; import tutorials.ThreadPool;public class Main {public static void main(String[] args) {ThreadPool pool = new ThreadPool(7);for (int i = 0; i < 5; i++) {Task task = new Task(i);pool.execute(task);} }在上面的示例中,我們使用notify()而不是notifyAll() 。 因?yàn)閚otify()具有比notifyAll()更理想的性能特征; 特別是, notify()導(dǎo)致更少的上下文切換,這在服務(wù)器應(yīng)用程序中很重要。 但是重要的是要確保在其他情況下使用notify() ,因?yàn)榕cnotify()關(guān)聯(lián)存在細(xì)微的風(fēng)險(xiǎn),并且僅在某些特定條件下使用它才是合適的。
下圖演示了以上示例中的線(xiàn)程池設(shè)計(jì)。
圖1。 線(xiàn)程池設(shè)計(jì)
2.有效使用線(xiàn)程池
線(xiàn)程池是一種用于構(gòu)造多線(xiàn)程應(yīng)用程序的強(qiáng)大機(jī)制,但并非沒(méi)有風(fēng)險(xiǎn)。 用線(xiàn)程池構(gòu)建的應(yīng)用程序可能具有與任何其他多線(xiàn)程應(yīng)用程序相同的并發(fā)風(fēng)險(xiǎn),例如死鎖 , 資源崩潰,同步或并發(fā)錯(cuò)誤,線(xiàn)程泄漏和請(qǐng)求重載 。
以下是一些要點(diǎn):
- 不要將同步等待其他任務(wù)的任務(wù)排隊(duì),因?yàn)檫@可能導(dǎo)致死鎖。
- 如果任務(wù)需要等待諸如I / O之類(lèi)的資源,請(qǐng)指定最大等待時(shí)間,然后使任務(wù)執(zhí)行失敗或重新排隊(duì)。 這保證了通過(guò)釋放線(xiàn)程執(zhí)行可能成功完成的另一個(gè)任務(wù)將取得一些進(jìn)展。
- 有效地調(diào)整線(xiàn)程池的大小,并了解線(xiàn)程太少或線(xiàn)程太多都會(huì)導(dǎo)致問(wèn)題。 線(xiàn)程池的最佳大小取決于可用處理器的數(shù)量以及工作隊(duì)列上任務(wù)的性質(zhì)。
3.結(jié)論
線(xiàn)程池對(duì)于組織服務(wù)器應(yīng)用程序很有用,并且正確地實(shí)現(xiàn)它以防止任何問(wèn)題(例如死鎖和wait()或notify()使用的復(fù)雜性)非常重要。 因此,建議考慮使用util.concurrent中的Executor類(lèi)之一,例如ThreadPoolExecutor ,而不是從頭開(kāi)始編寫(xiě)線(xiàn)程池。 如果要求創(chuàng)建線(xiàn)程來(lái)處理短期任務(wù),則可以考慮使用線(xiàn)程池。
4.下載源代碼
這是線(xiàn)程池的教程,要下載源代碼,請(qǐng)單擊此處 。
翻譯自: https://www.javacodegeeks.com/2016/12/implement-thread-pool-java.html
總結(jié)
以上是生活随笔為你收集整理的如何在Java中实现线程池的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 白马寺的由来及历史(中国第一古刹之洛阳白
- 下一篇: 使用Java更新DynamoDB项