「Java⼯具类」java线程池⼯具类,⾃定义线程池⼯具类
介绍语
本博客主要是Java常⽤关键技术点,通⽤⼯具类的分享;以及
springboot+springcloud+Mybatisplus+druid+mysql+redis+swagger+maven+docker等集成框架的技术分享;datax、kafka、flink等⼤数据处理框架的技术分享。⽂章会不断更新,欢迎码友关注点赞收藏转发!
关注多的话,后⾯会录制⼀些视频教程,图⽂和视频结合,⽐如:图书介绍⽹站系统、抢购系统、⼤数据中台系统等。技术才是程序猿的最爱,码友们冲啊
正⽂:
java核⼼之⼀就是线程,⽽⽤线程池执⾏线程是好的⽅式。下⾯是我封装的⼀个线程池⼯具类,简单实⽤。欢迎收藏备⽤!
为什么需要⼀个线程池⼯具类?
答:整个项⽬,⽤到线程执⾏任务的地⽅很多,不可能哪⾥⽤到就在那⾥直接new⼀个线程执⾏,这样资源得不到重复利⽤,⼀旦线程过多就会导致内存不⾜。
线程池的好处是什么?
使⽤线程池执⾏线程任务,当⼀个线程执⾏完成⼀个任务之后,线程资源回到线程池,资源得到重复利⽤。
线程池为什么使⽤⾃定义⽅式?
阿⾥⽂档推荐使⽤⾃定义线程池,因为java⾃带线程池都会有可能造成内存不⾜的问题。⾃定义线程池,根据服务器配置定制线程池核⼼线程、最⼤线程等,是最好的⽅式。
我封装的线程池⼯具类有什么好处?
使⽤线程安全的⽅式定义,整个项⽬不会重复创建线程池。线程池根据服务器cpu核数创建合适的核⼼线程数和最⼤线程数,达到不少创建不多创建刚刚好的配置。使⽤静态⽅法调⽤,随处可⽤,零难度上⼿。可以执⾏⽆返回值线程任务,可以执⾏有返回值的线程任务。
⼯具类
urrent.ThreadFactoryBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import urrent.*;
/**
* ⾃定义线程创建⼯具类,创建线程池后不需要关闭
*
* @author liangxn
*/
public class ThreadPoolUtils {
private static final Logger LOGGER = Logger(ThreadPoolUtils.class);
private static ThreadPoolExecutor threadPool = null;
private static final String POOL_NAME = "myPool";
// 等待队列长度
private static final int BLOCKING_QUEUE_LENGTH = 1000;
// 闲置线程存活时间
private static final int KEEP_ALIVE_TIME = 60 * 1000;
private ThreadPoolUtils() {
throw new IllegalStateException("utility class");
}
/**
* ⽆返回值直接执⾏
* ⽆返回值直接执⾏
*
* @param runnable 需要运⾏的任务
*/
public static void execute(Runnable runnable) {
getThreadPool().execute(runnable);
}
/**
* 有返回值执⾏
* 主线程中使⽤()获取返回值时,会阻塞主线程,直到任务执⾏完毕
*
* @param callable 需要运⾏的任务
*/
public static <T> Future<T> submit(Callable<T> callable) {
return getThreadPool().submit(callable);
}
private static synchronized ThreadPoolExecutor getThreadPool() {
if (threadPool == null) {
// 获取处理器数量
int cpuNum = Runtime().availableProcessors();
// 根据cpu数量,计算出合理的线程并发数
int maximumPoolSize = cpuNum * 2 + 1;
/
/ 核⼼线程数、最⼤线程数、闲置线程存活时间、时间单位、线程队列、线程⼯⼚、当前线程数已经超过最⼤线程数时的异常处理策略            threadPool = new ThreadPoolExecutor(maximumPoolSize - 1,
maximumPoolSize,
KEEP_ALIVE_TIME,
TimeUnit.MILLISECONDS,
new LinkedBlockingDeque<>(BLOCKING_QUEUE_LENGTH),
new ThreadFactoryBuilder().setNameFormat(POOL_NAME + "-%d").build(),
new ThreadPoolExecutor.AbortPolicy() {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
LOGGER.warn("线程爆炸了,当前运⾏线程总数:{},活动线程数:{}。等待队列已满,等待运⾏任
务数:{}",
}
});
}
return threadPool;
}
}
例⼦1:
Future<String> future = ThreadPoolUtils.submit(() -> {
return "我有返回值哦";
});
try {
logger.());
} catch (InterruptedException | ExecutionException e) {
<("任务超过指定时间未返回值,线程超时退出");
}
// 控制台打印⽇志:
21:04:19.428 [main] INFO  - 我有返回值哦
例⼦2:
Future<String> futureTimeout = ThreadPoolUtils.submit(() -> {
Thread.sleep(99999999);
return "我有返回值,但是超时了";
});
try {
// 建议使⽤该⽅式执⾏任务,不会导致线程因为某写原因⼀直占⽤线程,    // 从⽽导致未知问题
// 注意使⽤局部try避免主线程异常,导致主线程⽆法继续执⾏
logger.(3, TimeUnit.SECONDS));
} catch (InterruptedException | ExecutionException e) {
java线程池创建的四种<("任务执⾏异常");
} catch (TimeoutException e) {
<("任务超过指定时间未返回值,线程超时退出");
}
// 控制台打印⽇志:
21:07:24.940 [main] ERROR - 任务超过指定时间未返回值,线程超时退出例⼦3:
int loop = 40;
for (int i = 0; i < loop; i++) {
logger.info("任务{}", i);
logger.info("⼲活好累");
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
logger.info("终于⼲完了");
});
}
logger.info("我在这⼉等着你回来等你回来");
// 控制台打印:
21:08:08.494 [main] INFO  - 任务0 ............
21:08:08.540 [main] INFO  - 任务5
21:08:08.541 [main] INFO  - 任务6
21:08:08.540 [myPool-4] INFO  - ⼲活好累
21:08:08.540 [myPool-1] INFO  - ⼲活好累
21:08:08.540 [myPool-3] INFO  - ⼲活好累 ............
21:08:08.543 [main] INFO  - 任务21
21:08:08.548 [main] INFO  - 任务22
21:08:08.548 [main] INFO  - 任务23
21:08:08.548 [myPool-21] INFO  - ⼲活好累
21:08:08.549 [main] INFO  - 任务24
21:08:08.549 [myPool-22] INFO  - ⼲活好累
21:08:08.549 [main] INFO  - 任务25
21:08:08.549 [myPool-23] INFO  - ⼲活好累
21:08:08.549 [main] INFO  - 任务26 ............
21:08:08.551 [myPool-1] INFO  - ⼲活好累
21:08:08.551 [myPool-6] INFO  - 终于⼲完了
21:08:08.551 [myPool-7] INFO  - 终于⼲完了
21:08:08.551 [myPool-5] INFO  - ⼲活好累
21:08:08.551 [main] INFO  - 任务35
21:08:08.551 [main] INFO  - 任务36
21:08:08.551 [main] INFO  - 任务37
21:08:08.551 [main] INFO  - 任务38
21:08:08.551 [main] INFO  - 任务39
21:08:08.551 [main] INFO  - 我在这⼉等着你回来等你回来 21:08:08.551 [myPool-2] INFO  - ⼲活好累
21:08:08.551 [myPool-3] INFO  - ⼲活好累
21:08:08.551 [myPool-8] INFO  - ⼲活好累
21:08:08.551 [myPool-6] INFO  - ⼲活好累
21:08:08.551 [myPool-7] INFO  - ⼲活好累
21:08:08.552 [myPool-13] INFO  - 终于⼲完了
21:08:08.552 [myPool-12] INFO  - 终于⼲完了 ............
21:08:08.561 [myPool-7] INFO  - 终于⼲完了
21:08:08.561 [myPool-3] INFO  - 终于⼲完了
例⼦4:
// 测试10个线程使⽤⼯具类
ExecutorService executorService = wFixedThreadPool(10); for (int i = 0; i < 10; i++) {
executorService.submit(new Runnable() {
@Override
public void run() {
final String name = Thread.currentThread().getName();
logger.info("[{}],⼲活好累", name);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
logger.info("[{}],终于⼲完了", name);
});
}
});
}
logger.info("不⽤等他,我们先⼲");
// 控制台打印:
21:11:49.946 [main] INFO  - 不⽤等他,我们先⼲
21:11:49.991 [myPool-4] INFO  - [pool-2-thread-7],⼲活好累
21:11:49.991 [myPool-3] INFO  - [pool-2-thread-2],⼲活好累
21:11:49.991 [myPool-5] INFO  - [pool-2-thread-5],⼲活好累
21:11:49.991 [myPool-8] INFO  - [pool-2-thread-6],⼲活好累
21:11:49.991 [myPool-1] INFO  - [pool-2-thread-3],⼲活好累
21:11:49.991 [myPool-2] INFO  - [pool-2-thread-9],⼲活好累
21:11:49.991 [myPool-9] INFO  - [pool-2-thread-10],⼲活好累
21:11:49.991 [myPool-7] INFO  - [pool-2-thread-1],⼲活好累
21:11:49.991 [myPool-6] INFO  - [pool-2-thread-4],⼲活好累
21:11:49.991 [myPool-0] INFO  - [pool-2-thread-8],⼲活好累
21:11:50.091 [myPool-7] INFO  - [pool-2-thread-1],终于⼲完了
21:11:50.091 [myPool-4] INFO  - [pool-2-thread-7],终于⼲完了
21:11:50.091 [myPool-5] INFO  - [pool-2-thread-5],终于⼲完了
21:11:50.091 [myPool-2] INFO  - [pool-2-thread-9],终于⼲完了
21:11:50.091 [myPool-0] INFO  - [pool-2-thread-8],终于⼲完了
21:11:50.091 [myPool-1] INFO  - [pool-2-thread-3],终于⼲完了
21:11:50.091 [myPool-8] INFO  - [pool-2-thread-6],终于⼲完了
21:11:50.091 [myPool-6] INFO  - [pool-2-thread-4],终于⼲完了
21:11:50.091 [myPool-3] INFO  - [pool-2-thread-2],终于⼲完了
21:11:50.091 [myPool-9] INFO  - [pool-2-thread-10],终于⼲完了
例⼦5:

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。