如何在Java中实现线程池
線程是獨立程序的執(zhí)行路徑。 在java中,每個線程都擴展java.lang.Thread類或實現(xiàn)java.lang.Runnable。
多線程是指在一個任務中同時執(zhí)行兩個或多個線程。在多線程中,每個任務可以具有多個線程,并且這些線程可以異步或同步地并行運行。 您可以在我在此處撰寫的有關多線程的另一教程中找到有關線程和多線程的更多信息。
1.什么是線程池
線程池代表一組執(zhí)行任務的工作線程,每個線程可以多次重用。 如果在所有線程都處于活動狀態(tài)時提交了新任務,則它們將在隊列中等待直到線程可用。 線程池實現(xiàn)在內(nèi)部使用LinkedBlockingQueue在隊列中添加和刪除任務。 我們通常想要的是一個工作隊列,該隊列與一組固定的工作線程組合在一起,該工作線程使用wait()和notify()來向等待線程發(fā)出新工作到達的信號。 以下示例顯示了一個簡單的工作隊列,該隊列是Runnable對象的隊列。 盡管沒有特別要求Thread API使用Runnable接口,但這是調(diào)度程序和工作隊列的常用約定。 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());}}}} }在處理隊列時,使用同步塊很重要,以控制線程對隊列的訪問。
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() 。 因為notify()具有比notifyAll()更理想的性能特征; 特別是, notify()導致更少的上下文切換,這在服務器應用程序中很重要。 但是重要的是要確保在其他情況下使用notify() ,因為與notify()關聯(lián)存在細微的風險,并且僅在某些特定條件下使用它才是合適的。
下圖演示了以上示例中的線程池設計。
圖1。 線程池設計
2.有效使用線程池
線程池是一種用于構造多線程應用程序的強大機制,但并非沒有風險。 用線程池構建的應用程序可能具有與任何其他多線程應用程序相同的并發(fā)風險,例如死鎖 , 資源崩潰,同步或并發(fā)錯誤,線程泄漏和請求重載 。
以下是一些要點:
- 不要將同步等待其他任務的任務排隊,因為這可能導致死鎖。
- 如果任務需要等待諸如I / O之類的資源,請指定最大等待時間,然后使任務執(zhí)行失敗或重新排隊。 這保證了通過釋放線程執(zhí)行可能成功完成的另一個任務將取得一些進展。
- 有效地調(diào)整線程池的大小,并了解線程太少或線程太多都會導致問題。 線程池的最佳大小取決于可用處理器的數(shù)量以及工作隊列上任務的性質(zhì)。
3.結論
線程池對于組織服務器應用程序很有用,并且正確地實現(xiàn)它以防止任何問題(例如死鎖和wait()或notify()使用的復雜性)非常重要。 因此,建議考慮使用util.concurrent中的Executor類之一,例如ThreadPoolExecutor ,而不是從頭開始編寫線程池。 如果要求創(chuàng)建線程來處理短期任務,則可以考慮使用線程池。
4.下載源代碼
這是線程池的教程,要下載源代碼,請單擊此處 。
翻譯自: https://www.javacodegeeks.com/2016/12/implement-thread-pool-java.html
總結
以上是生活随笔為你收集整理的如何在Java中实现线程池的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 白马寺的由来及历史(中国第一古刹之洛阳白
- 下一篇: 使用Java更新DynamoDB项