Java-线程池(八股)

创建方法:Java原生创建线程池与Spring创建线程池

Java原生创建线程池:

一、手动创建ThreadPollExecutor

java 复制代码
// Java原生线程池核心构造方法
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(
    int corePoolSize,        // 核心参数1:核心线程数(常驻线程数)
    int maximumPoolSize,     // 核心参数2:最大线程数(线程池能创建的最大线程数)
    long keepAliveTime,      // 核心参数3:空闲线程存活时间
    TimeUnit unit,           // 核心参数4:存活时间的单位(秒/毫秒等)
    BlockingQueue<Runnable> workQueue,  // 核心参数5:任务阻塞队列(核心线程满了放这里)
    ThreadFactory threadFactory,        // 核心参数6:线程工厂(自定义线程名称、优先级等)
    RejectedExecutionHandler handler     // 核心参数7:拒绝策略(队列满+线程满时的处理方式)
);

二、Spring创建线程池

核心类是ThreadPoolTaskExecutor。

纯注解方式(@Configuration+@Bean,SpringBoot首选)

代码示例:

步骤一:编写线程类的核心配置类:
java 复制代码
@Configuration
public class SpringThreadPoolConfig {
    @Bean("customThreadPool")
    public Executor customThreadPool() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(2);
        executor.setMaxPoolSize(5);
        executor.setQueueCapacity(10);
        executor.setKeepAliveSeconds(30);
        executor.setThreadNamePrefix("SPRING-THREAD-POOL-");
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // 初始化线程池(必须调用,否则线程池不生效)
        executor.initialize();
        return executor;
    }
}
步骤二:业务代码中注入并使用线程池
java 复制代码
@Service
public class ThreadPoolService {

    // 注入线程池:@Qualifier指定Bean的名称,避免多个线程池时注入失败
    @Autowired
    @Qualifier("customThreadPool")
    private Executor customThreadPool;

    // 业务方法中执行异步任务
    public void doAsyncTask() {
        for (int i = 1; i <= 5; i++) {
            int finalI = i;
            customThreadPool.execute(() -> {
                System.out.println(Thread.currentThread().getName() + " 执行异步任务:" + finalI);
                try { Thread.sleep(1000); } catch (InterruptedException e) {e.printStackTrace();}
            });
        }
    }
}

三、Spring线程池(@Async异步注解)

步骤1:在配置类上添加@EnbaleAsync注解(开启异步支持)
java 复制代码
@Configuration
@EnableAsync
public class SpringThreadPoolConfig {
    @Bean("customThreadPool")
    public Executor customThreadPool() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(2);
        executor.setMaxPoolSize(5);
        executor.setQueueCapacity(10);
        executor.setKeepAliveSeconds(30);
        executor.setThreadNamePrefix("SPRING-THREAD-POOL-");
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;
    }
}
步骤2:在业务方法上添加@Async(线程池Bean名)注解
java 复制代码
@Service
public class AsyncTaskService {

    /**
     * 被@Async注解的方法,会被自动提交到指定的线程池异步执行
     * 无需手动调用线程池,Spring自动处理,无感知!
     */
    @Async("customThreadPool")
    public void doAsyncTask(int taskId) {
        System.out.println(Thread.currentThread().getName() + " 执行异步任务:" + taskId);
        try { Thread.sleep(1000); } catch (InterruptedException e) {e.printStackTrace();}
    }
}
步骤3:调用该方法即可(同步调用,异步执行)
java 复制代码
@Controller
public class TaskController {
    @Autowired
    private AsyncTaskService asyncTaskService;

    @GetMapping("/task")
    public String doTask() {
        for (int i = 1; i <= 5; i++) {
            // 同步调用,但方法内部会异步执行
            asyncTaskService.doAsyncTask(i);
        }
        return "success";
    }
}

线程池的种类:

1、newCachedThreadPool

创建一个可缓存线程池,如果当前线程池的长度超过了处理的需要时,它可以灵活的回收空闲的线程。当需要增加的时候,可以灵活的添加新的线程,不会对线程的长度做出任何限制。

2、newFixedThreadPool

创建一个定长线程池,可以控制线程最大并发数,超出的线程会在队列中等待。

3、newScheduledThreadPool

创建一个固定长度的线程池,支持定时的以及周期性的任务执行

4、newSingleThreadExecutor

创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,如果这个唯一的线程因为异常结束,那么会有一个新的线程来代替它,它保证前一项任务执行完毕后才执行后一项。保证所有任务按照指定顺序执行。

线程池的拒绝策略:

AbortPolicy,默认

线程池的默认拒绝策略,如果线程池满了丢掉这个任务并且抛出RejectedExecutionExcepitio异常

DiscardPolicy

是AbortPolicy的silent版本,如果线程池队列满了,会直接丢掉这个任务并且不会有任何异常。

DiscardOldestPolicy

丢弃最老的。如果队列满了,会将最早进入队列的任务删掉腾出空间,再尝试加入队列。

CallerRunsPolicy

如果添加到线程池失败,那么调用线程会自己去执行该任务,不会等待线程池中的线程去执行。

相关推荐
带刺的坐椅2 小时前
又一个项级的 Java Multi Agent 开源项目
java·ai·agent·solon·智能体
Voyager_42 小时前
StringRedisTemplate 和 RedisTemplate 的区别是什么?
java·spring boot
杏花春雨江南2 小时前
JavaWeb企业级项目实战:从SSH到SSM演进 + MQ/Redis/ES高可用架构落地全复盘(实战干货+避坑指南)
java·jvm·spring
UR的出不克2 小时前
使用 Python 爬取 Bilibili 弹幕数据并导出 Excel
java·python·excel
niaiheni2 小时前
PHP文件包含
开发语言·php
初次见面我叫泰隆2 小时前
Qt——1、初识Qt
开发语言·c++·qt
Arms2063 小时前
python时区库学习
开发语言·python·学习
短剑重铸之日3 小时前
《7天学会Redis》特别篇: Redis分布式锁
java·redis·分布式·后端·缓存·redission·看门狗机制
无名的小三轮3 小时前
第二章 信息安全概述
开发语言·php