更新時間:2022-06-24 09:37:41 來源:動力節(jié)點(diǎn) 瀏覽2187次
Java實(shí)現(xiàn)創(chuàng)建線程池要怎么做?動力節(jié)點(diǎn)小編來告訴大家。線程池是可以“重用”執(zhí)行任務(wù) 的池線程,這樣每個線程可以執(zhí)行多個任務(wù)。線程池是為您需要執(zhí)行的每個任務(wù)創(chuàng)建新線程的替代方法。
與重用已創(chuàng)建的線程相比,創(chuàng)建新線程會帶來性能開銷。這就是為什么重用現(xiàn)有線程來執(zhí)行任務(wù)比為每個任務(wù)創(chuàng)建一個新線程會導(dǎo)致更高的總吞吐量。
此外,使用線程池可以更輕松地控制一次有多少線程處于活動狀態(tài)。每個線程都會消耗一定量的計算機(jī)資源,比如內(nèi)存(RAM),所以如果你有太多線程同時處于活動狀態(tài),那么消耗的資源總量(比如RAM)可能會導(dǎo)致計算機(jī)變慢——例如,如果消耗了太多 RAM,以至于操作系統(tǒng) (OS) 開始將 RAM 換出到磁盤。
線程池通常用于多線程服務(wù)器。通過網(wǎng)絡(luò)到達(dá)服務(wù)器的每個連接都被包裝為一個任務(wù)并傳遞到線程池。線程池中的線程將同時處理連接上的請求。稍后將詳細(xì)介紹在 Java 中實(shí)現(xiàn)多線程服務(wù)器。
Java 在包中帶有內(nèi)置的線程池java.util.concurrent,因此您不必實(shí)現(xiàn)自己的線程池。您可以在我關(guān)于java.util.concurrent.ExecutorService的文本中閱讀有關(guān)它的更多信息 。無論如何,了解線程池的實(shí)現(xiàn)仍然很有用。
這是一個簡單的線程池實(shí)現(xiàn)。該實(shí)現(xiàn)使用 Java 5 附帶 的標(biāo)準(zhǔn)Java BlockingQueue 。
導(dǎo)入 java.util.ArrayList;
導(dǎo)入 java.util.List;
導(dǎo)入 java.util.concurrent.ArrayBlockingQueue;
導(dǎo)入 java.util.concurrent.BlockingQueue;
公共類線程池 {
私有阻塞隊列任務(wù)隊列=空;
私有列表<PoolThreadRunnable> runnables = new ArrayList<>();
私有布爾 isStopped = false;
公共線程池(int noOfThreads,int maxNoOfTasks){
taskQueue = new ArrayBlockingQueue(maxNoOfTasks);
for(int i=0; i<noOfThreads; i++){
PoolThreadRunnable poolThreadRunnable =
新的 PoolThreadRunnable(taskQueue);
runnables.add(new PoolThreadRunnable(taskQueue));
}
for(PoolThreadRunnable runnable : runnables){
新線程(可運(yùn)行).start();
}
}
公共同步無效執(zhí)行(可運(yùn)行任務(wù))拋出異常{
如果(this.isStopped)拋出
new IllegalStateException("線程池已停止");
this.taskQueue.offer(任務(wù));
}
公共同步無效停止(){
this.isStopped = true;
for(PoolThreadRunnable runnable : runnables){
runnable.doStop();
}
}
公共同步無效 waitUntilAllTask??sFinished() {
而(this.taskQueue.size()> 0){
嘗試 {
線程.sleep(1);
} 捕捉(InterruptedException e){
e.printStackTrace();
}
}
}
}
下面是實(shí)現(xiàn) Runnable 接口的 PoolThreadRunnable 類,因此它可以由 Java 線程執(zhí)行:
導(dǎo)入 java.util.concurrent.BlockingQueue;
公共類 PoolThreadRunnable 實(shí)現(xiàn) Runnable {
私有線程線程 = null;
私有阻塞隊列任務(wù)隊列=空;
私有布爾 isStopped = false;
公共 PoolThreadRunnable(BlockingQueue 隊列){
任務(wù)隊列 = 隊列;
}
公共無效運(yùn)行(){
this.thread = Thread.currentThread();
而(!isStopped()){
嘗試{
Runnable runnable = (Runnable) taskQueue.take();
可運(yùn)行的.run();
} 捕捉(異常 e){
//記錄或以其他方式報告異常,
//但保持池線程處于活動狀態(tài)。
}
}
}
公共同步無效doStop(){
isStopped = true;
//從 dequeue() 調(diào)用中中斷池線程。
this.thread.interrupt();
}
公共同步布爾 isStopped(){
返回已停止;
}
}
最后是如何使用上面的 ThreadPool 的示例:
公共類 ThreadPoolMain {
公共靜態(tài) void main(String[] args) 拋出異常 {
線程池 threadPool = new ThreadPool(3, 10);
for(int i=0; i<10; i++) {
int taskNo = i;
threadPool.execute(() -> {
字符串消息 =
Thread.currentThread().getName()
+ ": 任務(wù)" + taskNo ;
System.out.println(消息);
});
}
threadPool.waitUntilAllTask??sFinished();
線程池.stop();
}
}
線程池實(shí)現(xiàn)由兩部分組成。ThreadPool作為線程池的公共接口的類PoolThread,以及實(shí)現(xiàn)執(zhí)行任務(wù)的線程的類。
為了執(zhí)行一個任務(wù),該方法ThreadPool.execute(Runnable r)以一個 Runnable實(shí)現(xiàn)作為參數(shù)被調(diào)用。內(nèi)部Runnable在 阻塞隊列中排隊,等待出隊。
Runnable將由空閑出列 并PoolThread執(zhí)行。PoolThread.run()您可以在方法中看到這一點(diǎn)。執(zhí)行完P(guān)oolThread 循環(huán)并嘗試再次使任務(wù)出隊,直到停止。
停止該ThreadPool方法ThreadPool.stop()被調(diào)用。調(diào)用的停止在isStopped成員內(nèi)部記錄。然后通過調(diào)用每個線程來停止池中的doStop()每個線程。請注意該 方法將如何在被調(diào)用后execute()拋出一個IllegalStateExceptionif 被調(diào)用。 execute()stop()
線程將在完成它們當(dāng)前正在執(zhí)行的任何任務(wù)后停止。注意 this.interrupt()調(diào)用PoolThread.doStop()。這可以確保在wait()調(diào)用內(nèi)部的taskQueue.dequeue() 調(diào)用中阻塞的線程會中斷wait()調(diào)用,并使dequeue()方法調(diào)用留下一個InterruptedExceptionthrows。這個異常在 PoolThread.run()方法中被捕獲,報告,然后isStopped檢查變量。由于isStopped現(xiàn)在是真的,PoolThread.run()將退出并且線程死亡。
以上就是關(guān)于“Java實(shí)現(xiàn)創(chuàng)建線程池”的介紹,大家如果想了解更多相關(guān)知識,不妨來關(guān)注一下動力節(jié)點(diǎn)的Java視頻教程,里面的課程內(nèi)容從入門到精通,細(xì)致全面,通俗易懂,適合小白學(xué)習(xí),希望對大家能夠有所幫助。
相關(guān)閱讀

初級 202925

初級 203221

初級 202629

初級 203743