自定义线程池封装

实体类

public class ExecutorDto {

    /**
     * id
     */
    private String id;

    /**
     * 名称
     */
    private String name;

    /**
     * 描述信息
     */
    private String description;

    /**
     * 创建时间
     */
    private Date createTime;

    public ExecutorDto(String id, String name, String description, Date createTime) {
        this.id = id;
        this.name = name;
        this.description = description;
        this.createTime = createTime;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public Date getCreateTime() {
        return createTime;
    }

    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(getClass().getSimpleName());
        sb.append(" [");
        sb.append(", id=").append(id);
        sb.append(", name=").append(name);
        sb.append(", description=").append(description);
        sb.append(", createTime=").append(createTime);
        sb.append("]");
        return sb.toString();
    }
}

继承Runnable接口 实现线程方法

public abstract class ExtendedRunnable implements Runnable {

    private static final Logger logger = LoggerFactory.getLogger(ExtendedRunnable.class);


    /**
     * 初始化启动线程执行的具体方法
     * 在start执行过程中,try catch中的异常信息要throw出来,或者不要使用try catch
     * @throws InterruptedException
     * @throws Exception
     */
    protected abstract void start() throws InterruptedException, Exception;

    /**
     * 线程info数据信息
     */
    private ExecutorDto executorDto;

    public ExtendedRunnable(ExecutorDto executorDto) {
        this.executorDto = executorDto;
    }

    public ExecutorDto getExecutorDto() {
        return executorDto;
    }

    public void setExecutorDto(ExecutorDto executorDto) {
        this.executorDto = executorDto;
    }

    @Override
    public void run() {
        if (StringUtils.isEmpty(executorDto.getId())){
            try {
                throw new Exception("请命名启动线程的id!");
            } catch (Exception e) {
                logger.error("线程Id为空",e);
            }
            return;
        }
        if (ThreadPoolExecutorConfig.RUNNING_MAP.containsKey(executorDto.getId())
                && ThreadPoolExecutorConfig.INFO_MAP.containsKey(executorDto.getId())){
            try {
                throw new Exception("请勿重复提交相同的线程id!");
            } catch (Exception e) {
                logger.error("线程Id重复",e);
            }
            return;
        }
        try {
            beforeExecute(executorDto, Thread.currentThread());
            this.start();
        } catch (InterruptedException e){
            logger.error("线程InterruptedException:"+executorDto.toString(),e);
        } catch (Exception e) {
            logger.error("线程未知Exception:"+executorDto.toString(),e);
        } finally {
            afterExecute(executorDto);
        }
    }

    protected void beforeExecute(ExecutorDto dto,Thread t){
        ThreadPoolExecutorConfig.RUNNING_MAP.put(dto.getId(), t);
        ThreadPoolExecutorConfig.INFO_MAP.put(dto.getId(),dto);
        logger.info("beforeExecute>> RUNING_MAP.size():"+ThreadPoolExecutorConfig.RUNNING_MAP.size()+", INFO_MAP.size():"+ThreadPoolExecutorConfig.INFO_MAP.size()+", 线程info"+dto.toString());
    }

    protected void afterExecute(ExecutorDto dto){
        ThreadPoolExecutorConfig.RUNNING_MAP.remove(dto.getId());
        ThreadPoolExecutorConfig.INFO_MAP.remove(dto.getId());
        logger.info("afterExecute>> RUNING_MAP.size():"+ThreadPoolExecutorConfig.RUNNING_MAP.size()+", INFO_MAP.size():"+ThreadPoolExecutorConfig.INFO_MAP.size()+", 线程info"+dto.toString());
    }
}

继承Runnable接口 实现 Latch 线程方法

public abstract class ExtendedLatchRunnable implements Runnable {

    private static final Logger logger = LoggerFactory.getLogger(ExtendedLatchRunnable.class);


    private CountDownLatch latch = null;

    /**
     * 初始化启动线程执行的具体方法
     * 在start执行过程中,try catch中的异常信息要throw出来,或者不要使用try catch
     * @throws InterruptedException
     * @throws Exception
     */
    protected abstract void start() throws InterruptedException, Exception;

    /**
     * 线程info数据信息
     */
    private ExecutorDto executorDto;

    public ExtendedLatchRunnable(ExecutorDto executorDto, CountDownLatch latch) {
        this.executorDto = executorDto;
        this.latch = latch;
    }

    public ExecutorDto getExecutorDto() {
        return executorDto;
    }

    public void setExecutorDto(ExecutorDto executorDto) {
        this.executorDto = executorDto;
    }

    @Override
    public void run() {
        if (StringUtils.isEmpty(executorDto.getId())){
            try {
                throw new Exception("请命名启动线程的id!");
            } catch (Exception e) {
                logger.error("线程Id为空",e);
            }
            return;
        }
        if (ThreadPoolExecutorConfig.RUNNING_MAP.containsKey(executorDto.getId())
                && ThreadPoolExecutorConfig.INFO_MAP.containsKey(executorDto.getId())){
            try {
                throw new Exception("请勿重复提交相同的线程id!");
            } catch (Exception e) {
                logger.error("线程Id重复",e);
            }
            return;
        }
        try {
            beforeExecute(executorDto, Thread.currentThread());
            this.start();
        } catch (InterruptedException e){
            logger.error("线程InterruptedException:"+executorDto.toString(),e);
        } catch (Exception e) {
            logger.error("线程未知Exception:"+executorDto.toString(),e);
        } finally {
            afterExecute(executorDto);
        }
    }

    protected void beforeExecute(ExecutorDto dto,Thread t){
        ThreadPoolExecutorConfig.RUNNING_MAP.put(dto.getId(), t);
        ThreadPoolExecutorConfig.INFO_MAP.put(dto.getId(),dto);
        logger.info("beforeExecute>> RUNING_MAP.size():"+ThreadPoolExecutorConfig.RUNNING_MAP.size()+", INFO_MAP.size():"+ThreadPoolExecutorConfig.INFO_MAP.size()+", 线程info"+dto.toString());
    }

    protected void afterExecute(ExecutorDto dto){
        ThreadPoolExecutorConfig.RUNNING_MAP.remove(dto.getId());
        ThreadPoolExecutorConfig.INFO_MAP.remove(dto.getId());
        logger.info("afterExecute>> RUNING_MAP.size():"+ThreadPoolExecutorConfig.RUNNING_MAP.size()+", INFO_MAP.size():"+ThreadPoolExecutorConfig.INFO_MAP.size()+", 线程info"+dto.toString());
        logger.info("latch size is " + latch.getCount());
        latch.countDown();
    }
}

线程配置类

@Configuration
@EnableAsync
public class ThreadPoolExecutorConfig {

    private static Logger logger = LoggerFactory.getLogger(ThreadPoolExecutorConfig.class);

    public static ConcurrentHashMap<String, Thread> RUNNING_MAP = new ConcurrentHashMap<>();
    public static HashMap<String, ExecutorDto> INFO_MAP = new HashMap<>();

    /**ThreadPoolExecutor的策略
    1 线程数量未达到corePoolSize,则新建一个线程(核心线程)执行任务
    2 线程数量达到了corePools,则将任务移入队列等待
    3 队列已满,新建线程(非核心线程)执行任务
    4 队列已满,总线程数又达到了maximumPoolSize,就会由(RejectedExecutionHandler)抛出异常
    */
    @Value("${task.executor.pool.size}")
    private Integer taskExecutorPoolSize = 5;

    @Value("${task.executor.queue.size}")
    private Integer taskExecutorQueueSize = 200;


    @Bean
    public Executor pushExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //配置核心线程数
        executor.setCorePoolSize(taskExecutorPoolSize);
        //配置最大线程数
        executor.setMaxPoolSize(taskExecutorPoolSize);
        // 设置线程活跃时间(秒)
        executor.setKeepAliveSeconds(30);
        //配置队列大小
        executor.setQueueCapacity(taskExecutorQueueSize);
        //配置线程池中的线程的名称前缀
        executor.setThreadNamePrefix("push-");

        // setRejectedExecutionHandler:当pool已经达到max size的时候,如何处理新任务
        /*
        AbortPolicy:用于被拒绝任务的处理程序,它将抛出RejectedExecutionException。
        CallerRunsPolicy:用于被拒绝任务的处理程序,不在新线程中执行任务,它直接在execute方法的调用线程中运行被拒绝的任务。
        DiscardOldestPolicy:用于被拒绝任务的处理程序,它放弃最旧的未处理请求,然后重试execute。
        DiscardPolicy:用于被拒绝任务的处理程序,默认情况下它将丢弃被拒绝的任务。
        */
        System.out.println("taskExecutorPoolSize:" + taskExecutorPoolSize + ";taskExecutorQueueSize" + taskExecutorQueueSize);
        executor.setRejectedExecutionHandler((r, t) -> {
            try {
                String id = DateUtils.formatDate(new Date(), "yyyyMMddHHmmss")+"-"+ IdGen.randomBase62(6);
                logger.warn("任务id:"+id+",线程池 pushExecutor 已经超出最大线程数,队列阻塞,等待可用空间再继续!目前队列数量:"
                        + t.getQueue().size()+"个,时间:"+new Date());
                t.getQueue().put(r);
                logger.warn("任务id:"+id+",线程池 pushExecutor 阻塞已经解除!");
            } catch (InterruptedException e) {
                logger.error("线程池 pushExecutor 阻塞异常:", e);
            }
        });
        //执行初始化
        executor.initialize();
        return executor;
    }
}

使用样例

	@Autowired
    @Qualifier(value = "commandExecutor")
    private Executor pushExecutor;
	

	pushExecutor.execute(new ExtendedRunnable(new ExecutorDto(id,"","",new Date())) {
                @Override
                protected void start() throws InterruptedException, Exception {

                    try {
                        //投标使用日志
                        long start = System.currentTimeMillis();
                        logger.info("开始...线程id【{}】,开始时间【{}】",id,start);

                       	// 具体业务
                        long end = System.currentTimeMillis();
                        long consume = end - start;
                        logger.info("结束...线程id【{}】,结束时间【{}】,耗时【{}】毫秒",id,end,consume);
                    } catch ( Exception e) {
                        logger.error(e.getClass().toString());
                        throw e;
                    }
                }
            });
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值