文章目录
描述
自定义线程池可以帮助我们掌握更多的线程自主权,方便于后期代码的维护和问题的排查。
应用知识点
- 自定义线程池
- 线程工厂
- 线程池关闭
- 线程池最佳线程数
在《Java Concurrency in Practice》一书中,给出了估算线程池大小的公式:
Nthreads = Ncpu x Ucpu x (1 + W/C),其中
Ncpu = CPU核心数
Ucpu = CPU使用率,0~1
W/C = 等待时间与计算时间的比率
public static void main(String [] args){
int CPU_numbers = Runtime.getRuntime().availableProcessors();
System.out.println("CPU_numbers="+CPU_numbers);
}
线程池拒绝策略
四种策略
使用CallerRunsPolicy【主线程参与任务执行】
DiscardOldestPolicy【FIFO】
DiscardPolicy【丢弃没异常】
AbortPolicy【丢弃抛异常】
默认策略
private static final RejectedExecutionHandler defaultHandler = new AbortPolicy();
代码
Maven
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>29.0-jre</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.72</version>
</dependency>
自定义 Java 线程池
- 支持 自定义线程工厂 namedThreadFactory
- 支持获取线程执行结果 newFutureTask
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import java.util.concurrent.*;
/**
* @Title: 线程池测试
* @Description: 线程池测试
* @Author: wujie
* @Version: v1.0
* @Date:2020-06-10
* @Updatedby:
*/
public class ThreadTest {
private final static int CORE_POOL_SIZE = 10;
private final static int MAX_I_MUM_POOL_SIZE = 10;
private final static long KEEP_ALIVE_TIME = 0L;
private final static int WORKQUEUE_SIZE = 1024;
/**
* 自定义线程名称,方便的出错的时候溯源
*/
private static ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("center-pool-%d").build();
private static ExecutorService threadPool = new ThreadPoolExecutor(CORE_POOL_SIZE, MAX_I_MUM_POOL_SIZE, KEEP_ALIVE_TIME,
TimeUnit.MILLISECONDS, new LinkedBlockingDeque(WORKQUEUE_SIZE), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy());
/**
* 获取线程池
*/
public static ExecutorService getThreadPool() {
return threadPool;
}
/**
* 获取线程池工厂
*/
public static ThreadFactory getThreadFactory(){
return namedThreadFactory;
}
/**
* 执行任务
* @param r
*/
public static void newTask(Runnable r) {
threadPool.execute(r);
}
/**
* 执行任务-需要获取线程执行结果
* @param r
*/
public static Future newFutureTask(Runnable r) {
return threadPool.submit(r);
}
/**
* 关闭线程池(如有在执行任务则等待)
*/
public static void destroyExecutorService(){
System.out.println("关闭线程池");
if(!threadPool.isShutdown()){
threadPool.shutdown();
}
}
/**
* 立即关闭线程池
*/
public static void destroyNowExecutorService(){
System.out.println("立即关闭线程池");
if(!threadPool.isShutdown()){
threadPool.shutdownNow();
}
}
/**
* 线程池是否关闭
* @return
*/
public static boolean isExecutorServiceDownNow(){
return threadPool.isShutdown();
}
}
自定义线程池的简单使用
自定义线程池结合 Thread
public class ThreadUseTest {
private static class MyThread extends Thread{
@Override
public void run() {
super.run();
System.out.println("自定义线程池,可以通过构造参数传参");
}
}
public static void main(String [] args){
ThreadTest.newTask(ThreadTest.getThreadFactory().newThread(new MyThread()));
ThreadTest.destroyExecutorService();
}
}
自定义线程池结合 Runnable
public class ThreadUseTest {
private static class MyRunnable implements Runnable{
@Override
public void run() {
System.out.println("自定义线程池,可以通过构造参数传参");
}
}
public static void main(String [] args){
ThreadTest.newTask(ThreadTest.getThreadFactory().newThread(new MyRunnable()));
ThreadTest.destroyExecutorService();
}
}
自定义线程池结合 Future (需要获取执行结果)
Futuretask 学习(如果了解 Future 可以直接看 “使用线程池执行 FutureTask”小标题,否则建议阅读全文)
参考资料
[1]、https://www.cnblogs.com/xhq1024/p/12125290.html