java线程池实战应用总结

一、线程池的创建方式

方式(一):通过构造函数ThreadPoolExecutor()方式创建线程池

步骤1:先构建线程池

public class AsyncTaskExecutor {
    /**
     * 核心线程数
     */
    private static final int corePoolSize = 10;

    /**
     * 最大线程数
     */
    private static final int maxPoolSize = 30;

    /**
     * 空闲线程回收时间
     * 空闲线程是指:当前线程池中超过了核心线程数之后,多余的空闲线程的数量
     */
    private static final int keepAliveTime = 100;

    /**
     * 任务队列/阻塞队列
     */
    private static final int blockingQueueSize = 99999;

    private static final ThreadPoolExecutor executorPool = new ThreadPoolExecutor(
            corePoolSize,
            maxPoolSize,
            keepAliveTime,
            TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue<>(blockingQueueSize),
            new ThreadFactoryBuilder().setNameFormat("AsyncTaskThread" + "-%d").build(),
            new ThreadPoolExecutor.CallerRunsPolicy()
    );

    /**
     * 异步任务执行
     *
     * @param task
     */
    public static void execute(Runnable task) {
        executorPool.execute(task);
    }
}

步骤2:通过实现Runnable接口,创建异步任务

@Slf4j
public class CommonTask implements Runnable {

    /**
     * 模块ID
     */
    private Long modelId;

    /**
     * 模块名称
     */
    private ModelEnum modelName;

    /**
     * 构造方法
     *
     * @param modelId
     * @param modelName
     */
    public CommonTask(Long modelId, ModelEnum modelName) {
        this.modelId = modelId;
        this.modelName = modelName;
    }

    @Override
    public void run() {
        log.info("start to process common task!!!");
        if (modelId.intValue() == ModelEnum.Chinese.getCode()) {
            String name = ModelEnum.Chinese.getValue();
            log.info("modelID = {}  modelName = {}", modelId, name);
        } else {
            modelName = ModelEnum.forValue(modelId.intValue());
            log.info("modelID = {}  modelName = {}", modelId, modelName.getValue());
        }
    }
}

枚举

public enum ModelEnum {

    Chinese(1, "语文"),

    Math(2, "数学"),

    English(3, "数学");

    /**
     * code
     */
    private int code;

    /**
     * value
     */
    private String value;

    /**
     * 映射结果集
     */
    private static final Map<Integer, ModelEnum> VALUE_MAP;

    static {
        VALUE_MAP = new HashMap<>();
        for (ModelEnum modelEnum : ModelEnum.values()) {
            VALUE_MAP.put(modelEnum.code, modelEnum);
        }
    }

    ModelEnum(int code, String value) {
        this.code = code;
        this.value = value;
    }

    public int getCode() {
        return code;
    }

    public String getValue() {
        return value;
    }

    /**
     * 根据code获取枚举实例
     *
     * @param code
     * @return
     */
    public static ModelEnum forValue(int code) {
        return VALUE_MAP.get(code);
    }

}

步骤3:验证

            //步骤1:创建异步任务
            CommonTask task = new CommonTask(1L, ModelEnum.Chinese);
            //步骤2:调用线程池异步执行任务
            AsyncTaskExecutor.execute(task);
            log.info("main thread over...");

结果如下:

2024-05-23 14:53:16.096  INFO 20652 --- [           main] com.example.demo.dao.UserDaoTest         : main thread over...
2024-05-23 14:53:16.097  INFO 20652 --- [yncTaskThread-0] com.example.demo.task.CommonTask         : start to process common task!!!
2024-05-23 14:53:16.097  INFO 20652 --- [yncTaskThread-0] com.example.demo.task.CommonTask         : modelID = 1  modelName = 语文

方式(二):构建ThreadPoolTaskExecutor线程池,将其声明为Bean,可以通过注入bean的方式和在方法上使用@Async(“asyncTaskExecutor”)这种注解方式使用此线程池

@Slf4j
@Configuration
@EnableAsync
public class TaskExecutor {

    @Value("${async.executor.thread.core_pool_size}")
    private int corePoolSize;

    @Value("${async.executor.thread.max_pool_size}")
    private int maxPoolSize;

    @Value("${async.executor.thread.queue_capacity}")
    private int queueCapacity;

    @Value("${async.executor.thread.name.deal_task}")
    private String taskNamePrefix;

    /**
     * 构建线程池 并将其声明为Bean
     * 方式1:可以通过注入的方式使用此线程池
     * 方式2:可以在方法上使用@Async("asyncTaskExecutor")这种注解方式使用此线程池
     *
     * @return
     */
    @Bean(name = "asyncTaskExecutor")
    public Executor asyncTaskExecutor() {
        log.info("start asyncTaskExecutor...");
        ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
        threadPoolTaskExecutor.setCorePoolSize(corePoolSize);
        threadPoolTaskExecutor.setMaxPoolSize(maxPoolSize);
        threadPoolTaskExecutor.setQueueCapacity(queueCapacity);
        threadPoolTaskExecutor.setThreadNamePrefix(taskNamePrefix);
        //拒绝策略:当前线程数已经达到最大线程数后,如何处理新任务
        //CallerRunsPolicy()不在新线程中执行任务,而是返回调用者所在的线程来执行
        threadPoolTaskExecutor.setRejectedExecutionHandler(
                new ThreadPoolExecutor.CallerRunsPolicy());
        threadPoolTaskExecutor.initialize();
        return threadPoolTaskExecutor;
    }
}

在application.yml中的配置

async:
  executor:
    thread:
      core_pool_size: 10
      max_pool_size: 10
      queue_capacity: 99999
      name:
        deal_task: DEAL-TASK-

使用方式1:在方法上使用@Async(“asyncTaskExecutor”)这种注解方式使用此线程池
使用方式2:通过注入的方式使用此线程池

@Slf4j
@Service
public class WorkServiceImpl implements WorkService {

    @Async("asyncTaskExecutor")
    public void doAsyncTask() throws InterruptedException {
        Thread.sleep(1000);
        log.info("do AsyncTask...");
    }
}
@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest
public class UserDaoTest {
    SqlSession sqlSession;

    @Resource
    private WorkService workService;

    @Resource
    private Executor asyncTaskExecutor;

    @Test
    public void test() {
        try {

            //方式1:在方法上使用@Async("asyncTaskExecutor")这种注解方式使用此线程池
            for (int i = 0; i < 5; i++) {
                workService.doAsyncTask();
            }
            log.info("main Thread over...");

            //方式2:通过注入的方式使用此线程池(方便)
            asyncTaskExecutor.execute(() -> {
                log.info("async task is running..");
            });
            Thread.sleep(5000);

        }catch (Exception e) {
            e.printStackTrace();
        }
    }
}
  • 6
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值