java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > java线程池

java线程池实战应用步骤详解

作者:时间_wys

这篇文章主要介绍了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();
        }
    }
}

到此这篇关于java线程池实战应用总结的文章就介绍到这了,更多相关java线程池内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文