线程池的创建⽅法总共有 7 种,但总体来说可分为 2 类:
- 通过 ThreadPoolExecutor 创建的线程池;
- 通过 Executors 创建的线程池
前置步骤
public class ThreadTask implements Runnable{
Logger logger = LoggerFactory.getLogger(ThreadDemo.class);
private String taskName;
public String getTaskName() {
return taskName;
}
public void setTaskName(String taskName) {
this.taskName = taskName;
}
public ThreadTask(String name) {
this.setTaskName(name);
}
@Override
public void run() {
logger.info("线程-----------{},执行",taskName);
}
}
public class FixedThreadDemo extends ThreadTask {
Logger logger = LoggerFactory.getLogger(ThreadDemo.class);
private Boolean isAdd ;
private static Integer count = 0;
public FixedThreadDemo(String name,Boolean isAdd ) {
super(name);
this.isAdd = isAdd;
}
private ReentrantLock lock = new ReentrantLock();
@Override
public void run() {
lock.lock();
for (int i = 0 ; i < 100;i++){
if (isAdd){
count++;
}else {
count--;
}
logger.info("线程{}--------运行,执行模式:{},执行结果:{}",this.getTaskName(),isAdd?"加线程":"减线程",count);
}
lock.unlock();
}
}
Executors 创建线程池
newFixedThreadPool()
Executors.newFixedThreadPool:创建⼀个固定⼤⼩的线程池,可控制并发的线程数,超出的线程会在队列中等待,直到一个线程可用。如果任何线程在关闭之前的执行过程中由于失败而终止,如果需要执行后续任务,则会有一个新线程取代它的位置。在显式关闭池之前,池中的线程将一直存在。
public class FixedThreadPool {
private ExecutorService executors;
private static Logger logger = LoggerFactory.getLogger(FixedThreadPool.class);
@PostConstruct
public void init(){
// 参数 1、表示池中允许存在的最大线程数
// 参数 2、表示一个线程,自己创建的,可以不用,主要用来记录日志
executors = Executors.newFixedThreadPool(2,r -> {
logger.info("创建线程:{} ",r.hashCode());
Thread thread = new Thread(r);
return thread;
});
}
// 自定义方法,用于执行线程任务
// 使用submit可以执行有返回值的任务或者是无返回值的任务;而execute只能执行不带返回值的任务。
public void executor(ThreadTask threadTask){
executors.submit(threadTask);
}
}
测试:
期望值:0 实际结果:0
由于创建线程池指定了 最大线程数是 2,当我在线程池中去加入线程的时候,此时符合2的场景,第三个线程会等待前两个线程中其中一个结束后才会执行。
newCachedThreadPool()
Executors.newCachedThreadPool:创建⼀个可缓存的线程池,若线程数超过处理所需,缓存⼀段时间后会回收,若线程数不够,则新建线程;
public class CachedThreadPool {
private static Logger logger = LoggerFactory.getLogger(CachedThreadPool.class);
private ExecutorService executorService;
public void init(){
executorService = Executors.newCachedThreadPool(t->{
logger.info("可缓存的线程池{}",t.hashCode());
return new Thread(t);
});
}
// 自定义方法,用于执行线程任务
// 使用submit可以执行有返回值的任务或者是无返回值的任务;而execute只能执行不带返回值的任务。
public void executor(ThreadTask threadTask){
executorService.submit(threadTask);
}
}
执行结果 0
newSingleThreadExecutor()
Executors.newSingleThreadExecutor:创建单个线程数的线程池,它可以保证先进先出的执⾏顺序;
/**
* @author zhangguangfeng
* @date 2024/8/15
* 创建单个线程数的线程池,它可以保证先进先出的执⾏顺序;
*/
public class SingleThreadPool {
private static Logger logger = LoggerFactory.getLogger(SingleThreadPool.class);
private ExecutorService executorService;
public void init(){
executorService = Executors.newSingleThreadExecutor(t->{
logger.info("可执⾏顺序的线程池{}",t.hashCode());
return new Thread(t);
});
}
// 自定义方法,用于执行线程任务
// 使用submit可以执行有返回值的任务或者是无返回值的任务;而execute只能执行不带返回值的任务。
public void executor(ThreadTask threadTask){
executorService.submit(threadTask);
}
}
public static void main(String[] args) {
ThreadTask task1 = new FixedThreadDemo("线程1",Boolean.TRUE);
ThreadTask task2 = new FixedThreadDemo("线程2",Boolean.FALSE);
// 执行顺序的线程池
SingleThreadPool singleThreadPool = new SingleThreadPool();
singleThreadPool.init();
singleThreadPool.executor(task1);
singleThreadPool.executor(task2);
}
在这里可以看到,在代码顺序上,先执行task1,后执行task2,查看运行结果是否如此,按照指定顺序执行。
可以看到,是按照顺序执行的,假设去设置优先级,是否会打乱这个顺序呢?
并不会打乱这个顺序,原因:如它的设定一样,只存在单个线程在执行,本质上就是单线程的。
newScheduledThreadPool()
Executors.newScheduledThreadPool:创建⼀个可以执⾏延迟任务的线程池;
public class SingleThreadPool {
private static Logger logger = LoggerFactory.getLogger(SingleThreadPool.class);
private ScheduledExecutorService scheduledExecutorService;
public void init(){
scheduledExecutorService = Executors.newScheduledThreadPool(2,t->{
logger.info("可延迟任务的线程池{}",t.hashCode());
return new Thread(t);
});
}
// 自定义方法,用于执行线程任务
public void executor(ThreadTask threadTask){
// 提交一个定时任务,在 5 秒后执行
scheduledExecutorService.schedule(threadTask,5, TimeUnit.SECONDS);
}
// 自定义方法,用于执行周期性任务
public void executorAtFixedRate(ThreadTask threadTask){
// 提交一个周期性任务,每5秒执行一次,初始延迟1秒
scheduledExecutorService.scheduleAtFixedRate(threadTask,1,5, TimeUnit.SECONDS);
}
}
运行结果:
可以看到,相隔五秒后才运行。
线程测试 周期任务,初始延迟1s,每个5s周期运行
Executors.newSingleThreadScheduledExecutor
创建⼀个单线程的可以执⾏延迟任务的线程池;
Executors.newWorkStealingPool
创建⼀个抢占式执⾏的线程池(任务执⾏顺序不确定)【JDK1.8 添加】
ThreadPoolExecutor
ThreadPoolExecutor:最原始的创建线程池的⽅式,它包含了 7 个参数可供设置,
ThreadPoolExecutor 参数说明
详细链接:https://blog.csdn.net/m0_48273471/article/details/124171220
标签:Executors,创建,void,private,几种,线程,执行,public From: https://www.cnblogs.com/zgf123/p/18360487