線程池之七大參數(shù)
我們知道,線程池的核心類是 ThreadPoolExecutor,構(gòu)造一個ThreadPoolExecutor需要7個參數(shù)!

int corePoolSize
線程池中的常駐核心線程數(shù)
int maximumPoolSize
線程池中能夠容納同時執(zhí)行的最大線程數(shù),此值必須大于等于1
long keepAliveTime
多余的空閑線程的存活時間。當(dāng)前池中的線程數(shù)量超過corePoolSize時,多余線程會被銷毀到只剩下corePoolSize個線程為至
TimeUnit unit
keepAliveTime的單位
BlockingQueue<Runnable> workQueue
任務(wù)隊(duì)列,被提交但未被執(zhí)行的任務(wù)。由阻塞隊(duì)列實(shí)現(xiàn),關(guān)于阻塞隊(duì)列我這篇文章有講解 http://www.itdecent.cn/p/862c93ab3203
ThreadFactory threadFactory
表示生產(chǎn)線程池中工作線程的工廠。用于創(chuàng)建線程,一般默認(rèn)即可
RejectedExecutionHandler handler
拒絕策略,表示當(dāng)隊(duì)列滿了,并且工作線程大于等于線程池的最大線程數(shù)(maximumPoolSize)時如何來拒絕請求執(zhí)行的runnable餓策略。
我的這篇文章有詳細(xì)的講解拒絕策略
http://www.itdecent.cn/p/bf6fabb7b459
實(shí)際上我們應(yīng)該如何使用線程池?
不允許直接使用jdk自帶的三種線程池
Executors.newCachedThreadPool();
Executors.newFixedThreadPool(5);
Executors.newSingleThreadExecutor();
工作中請使用自定義的寫法:直接使用ThreadPoolExecutor類帶上7個參數(shù)構(gòu)造線程池!因?yàn)榭赡軐?dǎo)致oom異常,所謂oom異常就是 java.lang.OutOfMemoryError:Java heap space

實(shí)際上請使用ThreadPoolExecutor類帶上7個參數(shù)來構(gòu)造線程池
-
注意指定隊(duì)列的長度,我這里是new LinkedBlockingQueue<>(3)。如果不指定3,則隊(duì)列長度為
Integer.MAX_VALUE,可能因?yàn)槿蝿?wù)的積累導(dǎo)致oom。
image.png maximumPoolSize在cpu密級型項(xiàng)目中請配置成
cup核心數(shù)+1==>Runtime.getRuntime().availableProcessors()+1
maximumPoolSize在io密級型項(xiàng)目中請配置成cpu核心數(shù)/阻塞系數(shù)
參數(shù)調(diào)整試驗(yàn)
使用如下代碼來構(gòu)造線程池。2個核心線程,5個最大數(shù)量,3個等待隊(duì)列席位。
ExecutorService executorService =
new ThreadPoolExecutor(
2,
5,
2, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(3),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy());
實(shí)驗(yàn)一,任務(wù)數(shù)量為6
import java.util.concurrent.*;
public class Test {
public static void main(String[] args) {
ExecutorService executorService = new ThreadPoolExecutor(2, 5, 2, TimeUnit.SECONDS, new LinkedBlockingQueue<>(3), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
try {
for (int i = 1; i <= 6; i++) {
executorService.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " 辦理業(yè)務(wù)");
}
});
}
} finally {
executorService.shutdown();
}
}
}
這里有6個任務(wù)。所以線程池的核心線程、等待隊(duì)列都被用完。還剩下1個任務(wù)(6-2-3=1),需要創(chuàng)建線程來執(zhí)行。所以執(zhí)行結(jié)果中打印了pool-1-thread-3,該線程即是線程池臨時創(chuàng)建出來的線程!

實(shí)驗(yàn)二,任務(wù)數(shù)量為9
package com.springboot.study.demo1;
import java.util.concurrent.*;
class Test1 {
public static void main(String[] args) {
//2個核心線程 等待數(shù)量席位3個 最大線程數(shù)5個,那么最大容納任務(wù)是8個
ExecutorService executorService = new ThreadPoolExecutor(2, 5, 2, TimeUnit.SECONDS, new LinkedBlockingQueue<>(3), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
try {
//提交9次任務(wù),超出的1個任務(wù)會被應(yīng)用拒絕策略
for (int i = 1; i <= 9; i++) {
executorService.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " 辦理業(yè)務(wù)");
}
});
}
} finally {
executorService.shutdown();
}
}
}
執(zhí)行結(jié)果:抱錯。此時任務(wù)數(shù)量9超過線程池可接受的最大任務(wù)數(shù)8(maximumPoolSize 3 +workQueue的容量5)
Exception in thread "main" java.util.concurrent.RejectedExecutionException: Task Test$1@42110406 rejected from java.util.concurrent.ThreadPoolExecutor@531d72ca[Running, pool size = 5, active threads = 5, queued tasks = 3, completed tasks = 0]
創(chuàng)建自定義線程工廠為線程池中線程命名
創(chuàng)建線程池時使用自定義的線程工廠,這樣可以為該線程池內(nèi)的線程改名
package io.renren;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
public class UserThreadFactory implements ThreadFactory {
private final String namePrefix;
private final AtomicInteger nextId = new AtomicInteger(1);
// 定義線程組名稱,在 jstack 問題排查時,非常有幫助
public UserThreadFactory(String whatFeaturOfGroup) {
namePrefix = "來自 UserThreadFactory 線程工廠的 " + whatFeaturOfGroup + "-線程-";
}
@Override
public Thread newThread(Runnable task) {
String name = namePrefix + nextId.getAndIncrement();
Thread thread = new Thread(null, task, name, 0);
System.out.println(thread.getName());
return thread;
}
}
class TestFa{
public static void main(String[] args) {
UserThreadFactory userThreadFactory = new UserThreadFactory(" 用戶 ");
ThreadPoolExecutor threadPoolExecutor =
new ThreadPoolExecutor(
2,
5,
2, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(3),
userThreadFactory ,
new ThreadPoolExecutor.AbortPolicy());
for (int i = 0; i <8 ; i++) {
threadPoolExecutor.submit(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
});
}
threadPoolExecutor.shutdown();
}
}
ThreadFactory 匿名
ThreadFactory threadFactory = new ThreadFactory() {
AtomicInteger nextId = new AtomicInteger(1);
@Override
public Thread newThread(Runnable task) {
Thread thread = new Thread(null, task, "測試redis分布式鎖線程" + nextId.getAndIncrement(), 0);
return thread;
}
};
ThreadPoolExecutor threadPoolExecutor =
new ThreadPoolExecutor(2,
5,
3,
TimeUnit.MINUTES,
new ArrayBlockingQueue<>(5),
threadFactory,
new ThreadPoolExecutor.AbortPolicy()
);
for (int i = 0; i <10 ; i++) {
threadPoolExecutor.submit(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
});
}
