java線(xiàn)程池詳解及代碼介紹
一.線(xiàn)程池簡(jiǎn)介
線(xiàn)程池的概念
線(xiàn)程池就是首先創(chuàng)建一些線(xiàn)程,它們的集合稱(chēng)為線(xiàn)程池,使用線(xiàn)程池可以很好的提高性能,線(xiàn)程池在系統(tǒng)啟動(dòng)時(shí)既創(chuàng)建大量空閑的線(xiàn)程,程序?qū)⒁粋€(gè)任務(wù)傳給線(xiàn)程池。線(xiàn)程池就會(huì)啟動(dòng)一條線(xiàn)程來(lái)執(zhí)行這個(gè)任務(wù),執(zhí)行結(jié)束后,該線(xiàn)程并不會(huì)死亡,而是再次返回線(xiàn)程池中成為空閑狀態(tài),等待執(zhí)行下一個(gè)任務(wù)。
線(xiàn)程池的工作機(jī)制
在線(xiàn)程池的編程模式下,任務(wù)是提交給整個(gè)線(xiàn)程池,而不是直接提交給某個(gè)線(xiàn)程,線(xiàn)程池在拿到任務(wù)后,就在內(nèi)部尋找是否有空閑的線(xiàn)程,如果有,則將任務(wù)交給某個(gè)空閑的線(xiàn)程
一個(gè)線(xiàn)程同時(shí)只能執(zhí)行一個(gè)任務(wù),但可以同時(shí)向一個(gè)線(xiàn)程池提交多個(gè)任務(wù)
使用線(xiàn)程池的原因
多線(xiàn)程運(yùn)行時(shí)間,系統(tǒng)不斷的啟動(dòng)和關(guān)閉新線(xiàn)程,成本非常高,會(huì)過(guò)度消耗系統(tǒng)資源,以及過(guò)渡切換線(xiàn)程的危險(xiǎn),從而導(dǎo)致系統(tǒng)資源的崩潰,這時(shí),線(xiàn)程池也就是最好的選擇了
二、四種常見(jiàn)的線(xiàn)程池詳解
線(xiàn)程池的返回值ExecutorService簡(jiǎn)介
ExecutorService是Java提供的用于管理線(xiàn)程池的類(lèi)。該類(lèi)的兩個(gè)作用:控制線(xiàn)程數(shù)量和重用線(xiàn)程
具體的4種常用的線(xiàn)程池實(shí)現(xiàn)
1-newCachedThreadPool:創(chuàng)建一個(gè)可緩存線(xiàn)程池,如果線(xiàn)程池長(zhǎng)度超過(guò)處理需要,可靈活回收空閑線(xiàn)程,若無(wú)可回收,則新建線(xiàn)程。
2-newFixedThreadPool:創(chuàng)建一個(gè)定長(zhǎng)線(xiàn)程池,可控制線(xiàn)程最大并發(fā)數(shù),超出的線(xiàn)程會(huì)在隊(duì)列中等待。
3-newScheduledThreadPool:創(chuàng)建一個(gè)定長(zhǎng)線(xiàn)程池,支持定時(shí)及周期性任務(wù)執(zhí)行。
4-newSingleThreadExecutor:創(chuàng)建一個(gè)單線(xiàn)程化的線(xiàn)程池,它只會(huì)用唯一的工作線(xiàn)程來(lái)執(zhí)行任務(wù),保證所有任務(wù)按照指定順序(FIFO, LIFO, 優(yōu)先級(jí))執(zhí)行;
1-Executors.newCacheThreadPool()
創(chuàng)建一個(gè)可緩存線(xiàn)程池,如果線(xiàn)程池長(zhǎng)度超過(guò)處理需要,可靈活回收空閑線(xiàn)程,若無(wú)可回收,則新建線(xiàn)程。
代碼如下:
/**
* @author: haijiao12138
* @ClassName: ThreadPoolExecutorDemo
* @description: TODO Executors.newCachedThreadPool() 創(chuàng)建一個(gè)可緩存線(xiàn)程池,如果線(xiàn)程池 長(zhǎng)
度超過(guò)處理處理需要,可靈活回收空閑線(xiàn)程 若無(wú)可回收 則創(chuàng)建新線(xiàn)程
* 常見(jiàn)的4種線(xiàn)程池的使用;
* @date: 2021/8/17 20:17
*/
public class ThreadPoolExecutorDemo {
public static void main(String[] args) {
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(1);
}catch (InterruptedException e) {
e.printStackTrace();
}
cachedThreadPool.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"正在被執(zhí)行");
}
});
}
}
}
運(yùn)行結(jié)果如下:

線(xiàn)程池為無(wú)限大,當(dāng)執(zhí)行第二個(gè)任務(wù)時(shí)第一個(gè)任務(wù)已經(jīng)完成,會(huì)復(fù)用執(zhí)行第一個(gè)任務(wù)的線(xiàn)程,而不用每次新建線(xiàn)程。(用休眠來(lái)實(shí)現(xiàn)第一個(gè)任務(wù)完成了);
2-Executors.newFixedThreadPool(int n) //括號(hào)中存放線(xiàn)程的數(shù)量
創(chuàng)建一個(gè)定長(zhǎng)線(xiàn)程池,可控制線(xiàn)程最大并發(fā)數(shù),超出的線(xiàn)程會(huì)在隊(duì)列中等待。
public class ThreadPoolExecutorDemo {
public static void main(String[] args) {
//四種常見(jiàn)的線(xiàn)程池
/*
1-newCachedThreadPool(); 創(chuàng)建一個(gè)可緩存線(xiàn)程池 如果線(xiàn)程池長(zhǎng)度超過(guò)處理需要 可靈活回收空閑線(xiàn)程 若無(wú)可回收 則新建線(xiàn)程
2-newFixedThreadPool(); 創(chuàng)建一個(gè)定長(zhǎng)線(xiàn)程池 可控制線(xiàn)程最大并發(fā)數(shù) 超出的線(xiàn)程 會(huì)在隊(duì)列中等得
3-newScheduledThreadPool();
4-newSingleThreadExecutor();
*/
//第二種線(xiàn)程池
//2-Executors.newFixedThreadPool(int n)
//創(chuàng)建一個(gè)定長(zhǎng)線(xiàn)程池,可控制線(xiàn)程最大并發(fā)數(shù),超出的線(xiàn)程會(huì)在隊(duì)列中等待。
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(10);//線(xiàn)程池種擁有三個(gè)線(xiàn)程
//創(chuàng)建一個(gè)定長(zhǎng)線(xiàn)程池,可控制線(xiàn)程最大并發(fā)數(shù),超出的線(xiàn)程會(huì)在隊(duì)列中等待
for (int i = 0; i < 10; i++) {
fixedThreadPool.execute(new Runnable() {
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName()+"正在執(zhí)行!");
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
}
}
執(zhí)行代碼如下:

3-Executors.newScheduledThreadPool(int n);//初始的時(shí)候 線(xiàn)程的個(gè)數(shù)
延遲5秒執(zhí)行一次:
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
for (int i = 0; i < 3; i++) {
scheduledThreadPool.schedule(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("延遲5秒執(zhí)行:"+Thread.currentThread().getName());
}
},5, TimeUnit.SECONDS);
}
表示延遲1秒后每3秒執(zhí)行一次:
public static void main(String[] args) {
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
//延遲1秒執(zhí)行
scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
System.out.println("延遲1秒后每3秒執(zhí)行一次:"+Thread.currentThread().getName());
}
}, 1,3 , TimeUnit.MICROSECONDS);
}
運(yùn)行結(jié)果如下:

4-Executors.newSingleThreadExecutor()
創(chuàng)建一個(gè)單線(xiàn)程化的線(xiàn)程池,它只會(huì)用唯一的工作線(xiàn)程來(lái)執(zhí)行任務(wù),保證所有任務(wù)按照指定順序(FIFO, LIFO, 優(yōu)先級(jí))執(zhí)行。
public static void main(String[] args) {
//第四種線(xiàn)程池:
//Executors.newSingleThreadExecutor()
//創(chuàng)建一個(gè)單線(xiàn)程化的線(xiàn)程池,它只會(huì)用唯一的工作線(xiàn)程來(lái)執(zhí)行任務(wù),保證所有任務(wù)按照指定順序(FIFO, LIFO, 優(yōu)先級(jí))執(zhí)行。
//創(chuàng)建一個(gè)單線(xiàn)程化的線(xiàn)程池
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
for (int i = 0; i < 10; i++) {
final int index = i;
singleThreadExecutor.execute(new Runnable() {
@Override
public void run() {
try {
//結(jié)果依次輸出,相當(dāng)于順序執(zhí)行各個(gè)任務(wù)
System.out.println(Thread.currentThread().getName()+"正在被執(zhí)行,打印的值是:"+index);
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
}
結(jié)果如下:

三、緩沖隊(duì)列BlockingQueue和自定義線(xiàn)程池ThreadPoolExecutor
緩沖隊(duì)列BlockingQueue簡(jiǎn)介:
BlockingQueue是雙緩沖隊(duì)列。BlockingQueue內(nèi)部使用兩條隊(duì)列,允許兩個(gè)線(xiàn)程同時(shí)向隊(duì)列一個(gè)存儲(chǔ),一個(gè)取出操作。在保證并發(fā)安全的同時(shí),提高了隊(duì)列的存取效率。
常用的幾種BlockingQueue:
ArrayBlockingQueue(int i):規(guī)定大小的BlockingQueue,其構(gòu)造必須指定大小。其所含的對(duì)象是FIFO順序排序的。
LinkedBlockingQueue()或者(int i):大小不固定的BlockingQueue,若其構(gòu)造時(shí)指定大小,生成的BlockingQueue有大小限制,不指定大小,其大小有Integer.MAX_VALUE來(lái)決定。其所含的對(duì)象是FIFO順序排序的。
PriorityBlockingQueue()或者(int i):類(lèi)似于LinkedBlockingQueue,但是其所含對(duì)象的排序不是FIFO,而是依據(jù)對(duì)象的自然順序或者構(gòu)造函數(shù)的Comparator決定。
SynchronizedQueue():特殊的BlockingQueue,對(duì)其的操作必須是放和取交替完成。
自定義線(xiàn)程池(ThreadPoolExecutor和BlockingQueue連用)自定義線(xiàn)程池,可以用ThreadPoolExecutor類(lèi)創(chuàng)建,它有多個(gè)構(gòu)造方法來(lái)創(chuàng)建線(xiàn)程池。
常見(jiàn)的構(gòu)造函數(shù):ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue)
示例代碼:
package com.haijiao12138.demo.leetcode.test0817.緩沖隊(duì)列;
/**
* @author: haijiao12138
* @ClassName: TempThread
* @description: TODO
* @date: 2021/8/18 22:24
*/
public class TempThread extends Thread {
@Override
public void run() {
// 打印正在執(zhí)行的緩存線(xiàn)程信息
System.out.println(Thread.currentThread().getName() + "正在被執(zhí)行");
try {
// sleep一秒保證3個(gè)任務(wù)在分別在3個(gè)線(xiàn)程上執(zhí)行
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
package com.haijiao12138.demo.leetcode.test0817.緩沖隊(duì)列;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* @author: haijiao12138
* @ClassName: TestThreadPoolExecutor
* @description: TODO
* @date: 2021/8/18 22:28
*/
public class TestThreadPoolExecutor {
public static void main(String[] args) {
// 創(chuàng)建數(shù)組型緩沖等待隊(duì)列
BlockingQueue<Runnable> bq = new ArrayBlockingQueue<Runnable>(10);
// ThreadPoolExecutor:創(chuàng)建自定義線(xiàn)程池,池ThreadPoolExecutor中保存的線(xiàn)程數(shù)為3,允許最大的線(xiàn)程數(shù)為6
ThreadPoolExecutor tpe = new ThreadPoolExecutor(3, 6, 50, TimeUnit.MILLISECONDS, bq);
// 創(chuàng)建3個(gè)任務(wù)
Runnable t1 = new TempThread();
Runnable t2 = new TempThread();
Runnable t3 = new TempThread();
// 3個(gè)任務(wù)在分別在3個(gè)線(xiàn)程上執(zhí)行
tpe.execute(t1);
tpe.execute(t2);
tpe.execute(t3);
// 關(guān)閉自定義線(xiàn)程池
tpe.shutdown();
}
}

總結(jié)
本篇文章就到這里了,希望能給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
- Java線(xiàn)程創(chuàng)建的四種方式總結(jié)
- Java線(xiàn)程通信中關(guān)于生產(chǎn)者與消費(fèi)者案例分析
- 手把手帶你理解java線(xiàn)程池之工作隊(duì)列workQueue
- 一篇文章帶你了解如何正確使用java線(xiàn)程池
- 超詳細(xì)講解Java線(xiàn)程池
- Java線(xiàn)程池詳細(xì)解讀
- Java線(xiàn)程的并發(fā)工具類(lèi)實(shí)現(xiàn)原理解析
- Java線(xiàn)程池中的各個(gè)參數(shù)如何合理設(shè)置
- 入門(mén)Java線(xiàn)程基礎(chǔ)一篇就夠了
- 解答為什么 Java 線(xiàn)程沒(méi)有Running狀態(tài)
相關(guān)文章
idea創(chuàng)建springboot項(xiàng)目和springcloud項(xiàng)目的詳細(xì)教程
這篇文章主要介紹了idea創(chuàng)建springboot項(xiàng)目和springcloud項(xiàng)目方法,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-10-10
SpringBoot3.0集成MybatisPlus的實(shí)現(xiàn)方法
本文主要介紹了SpringBoot3.0集成MybatisPlus的實(shí)現(xiàn)方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-08-08
Java文件拒絕訪(fǎng)問(wèn)問(wèn)題及解決
這篇文章主要介紹了Java文件拒絕訪(fǎng)問(wèn)問(wèn)題及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12
File的API和常用方法詳解_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
這篇文章主要為大家詳細(xì)介紹了File的API和常用方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-05-05
Java實(shí)現(xiàn)文件分片上傳接口的示例代碼
這篇文章主要為大家詳細(xì)介紹了如何利用Java語(yǔ)言實(shí)現(xiàn)文件分片上傳的功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起了解一下2022-07-07
java虛擬機(jī)原理:Class字節(jié)碼二進(jìn)制文件分析
class文件全名稱(chēng)為Java class文件,主要在平臺(tái)無(wú)關(guān)性和網(wǎng)絡(luò)移動(dòng)性方面使Java更適合網(wǎng)絡(luò)。它在平臺(tái)無(wú)關(guān)性方面的任務(wù)是:為Java程序提供獨(dú)立于底層主機(jī)平臺(tái)的二進(jìn)制形式的服務(wù)。下面我們來(lái)詳細(xì)解讀下它吧2021-09-09
Java并發(fā)Lock接口實(shí)現(xiàn)示例詳解
這篇文章主要為大家介紹了Java并發(fā)Lock接口,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-06-06

