public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue workQueue,
ThreadFactory threadFactory) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
threadFactory, defaultHandler);
}
参数名 | 说明 |
corePoolSize | 核心线程数量(常驻) |
maximumPoolSize |
最大线程数量 |
keepAliveTime |
临时线程存活时间 |
unit |
存活时间单位 |
workQueue |
队列 |
threadFactory |
线程池创建线程对应的工厂 |
定义一个线程池包装类(方便使用,也可以使用时候直接创建)
package com.hz.threadpool;
import java.io.Closeable;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @description:
* @author: pp_lan
* @date: 2022/3/15
*/
public class CustomThreadPool implements Closeable {
private ThreadPoolExecutor pool;
private AtomicInteger count = new AtomicInteger();
private CustomThreadPool(int core, int max, int queueSize, String threadName) {
this.pool = new ThreadPoolExecutor(core, max, 3, TimeUnit.SECONDS, new ArrayBlockingQueue<>(queueSize),
r -> new Thread(r, threadName + count.getAndIncrement()));
}
public ThreadPoolExecutor getPool() {
return pool;
}
/**
* 获取对象
* @param core
* @param max
* @param queueSize
* @param threadName
* @return
*/
public static CustomThreadPool initPool(int core, int max, int queueSize, String threadName) {
return new CustomThreadPool(core, max, queueSize, threadName);
}
/**
* callable批量任务
* @param tasks
* @param
* @return
*/
public List> invokeAll(Collection extends Callable> tasks) {
try {
List> futures = this.pool.invokeAll(tasks);
return futures;
} catch (InterruptedException e) {
throw new RuntimeException("线程被中断", e);
}
}
/**
* callable单个任务
* @param task
* @param
* @return
*/
public Future submit(Callable task) {
return this.pool.submit(task);
}
/**
* runnable任务
* @param runnable
*/
public void execute(Runnable runnable) {
this.pool.execute(runnable);
}
/**
* runnable任务
* @param runnable
*/
public Future> submit(Runnable runnable) {
return this.pool.submit(runnable);
}
/**
* 线程池关闭,建议使用try-resource进行自动关闭,不要手动执行
*/
public void shutdown() {
this.pool.shutdown();
try {
if (!this.pool.awaitTermination(1, TimeUnit.MINUTES)) {
this.pool.shutdownNow();
if (!this.pool.awaitTermination(1, TimeUnit.MINUTES)) {
throw new RuntimeException("线程池关闭失败");
}
}
} catch (InterruptedException e) {
throw new RuntimeException("线程池关闭失败", e);
}
}
@Override
public void close() {
this.shutdown();
}
}
package com.hz.task;
import java.util.concurrent.TimeUnit;
/**
* 任务
*
* @author pp_lan
*/
public class Task implements Runnable {
private int index;
public Task(int index) {
this.index = index;
}
@Override
public void run() {
System.out.println("-------------执行任务" + index);
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
package com.hz.task;
import com.hz.threadpool.CustomThreadPool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Queue;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;
/**
* 线程池调参
*
* @author pp_lan
*/
public class ThreadPoolParamFixedDemo {
private static final Logger LOGGER = LoggerFactory.getLogger(ThreadPoolParamFixedDemo.class);
public static void main(String[] args) {
Queue queue = new LinkedBlockingDeque<>();
try (CustomThreadPool pool = CustomThreadPool.initPool(2, 20, 5, "线程池")) {
for (int i = 0; i < 7; i++) {
queue.add(new Task(i));
}
new Thread(() -> {
while (true) {
Runnable task = queue.poll();
if (task != null) {
pool.execute(task);
} else {
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
LOGGER.error("休眠被中断", e);
}
}
}
}).start();
int activeCount = 1;
while (activeCount > 0) {
try {
System.out.println("wait...");
TimeUnit.SECONDS.sleep(1);
activeCount = pool.getPool().getActiveCount();
} catch (InterruptedException e) {
LOGGER.error("中断异常", e);
}
}
}
}
}
运行结果:
wait...
-------------执行任务0
-------------执行任务1
wait...
-------------执行任务2
-------------执行任务3
wait...
-------------执行任务4
-------------执行任务5
wait...
-------------执行任务6
wait...
wait...
此时,从运行结果可见:线程数量=coreSize。
创建新的线程
public static void main(String[] args) {
...
for (int i = 0; i < 25; i++) {
queue.add(new Task(i));
}
...
}
运行结果:
wait...
-------------执行任务0
-------------执行任务1
-------------执行任务7
-------------执行任务8
-------------执行任务9
-------------执行任务10
-------------执行任务11
-------------执行任务12
-------------执行任务13
-------------执行任务14
-------------执行任务15
-------------执行任务16
-------------执行任务17
-------------执行任务19
-------------执行任务20
-------------执行任务21
-------------执行任务22
-------------执行任务18
-------------执行任务23
-------------执行任务24
wait...
-------------执行任务2
-------------执行任务3
-------------执行任务4
-------------执行任务5
-------------执行任务6
wait...
wait...
wait...
Disconnected from the target VM, address: '127.0.0.1:35445', transport: 'socket'
Process finished with exit code 130 (interrupted by signal 2: SIGINT)
此时,运行结果可见:coreSize <= 线程数量<=maxSize。
public static void main(String[] args) {
...
for (int i = 0; i < 26; i++) {
queue.add(new Task(i));
}
...
}
运行结果:
-------------执行任务21
-------------执行任务22
-------------执行任务24
-------------执行任务23
Exception in thread "Thread-0" java.util.concurrent.RejectedExecutionException: Task com.hz.task.Task@73c8c9df rejected from java.util.concurrent.ThreadPoolExecutor@625fdb98[Running, pool size = 20, active threads = 20, queued tasks = 5, completed tasks = 0]
at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2063)
at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:830)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1379)
at com.hz.threadpool.CustomThreadPool.execute(CustomThreadPool.java:72)
at com.hz.task.TaskQueue.lambda$main$0(TaskQueue.java:33)
at java.lang.Thread.run(Thread.java:748)
wait...
任务满了,多余任务添加入线程池则执行拒绝策略。
以demo中的数据为例,coreSize(2), queueSize(5), maxSize(20),实时任务和线程数量对应关系如下所示:
实时任务数量 | 线程数量 |
[0, 7] | 2 |
(7, 25] | (2, 20] |
(25, +\infty) | (2, 20], 且多余任务执行拒绝策略,例如报错 |
注意:
因为只有当taskSize > coreSize + queueSize才会创建新线程,所以创建线程池时候队列需要指定队列长度(反例: new LinkedBlockingDeque()),否则会导致线程数一直为核心线程,即使任务阻塞甚至被拒绝也无法扩展到最大核心数对应的线程数量。
LinkedBlockingDeque对应构造函数如下:
public LinkedBlockingDeque() {
this(Integer.MAX_VALUE);
}