线程池的定义,以及简单的使用,Runable和Callable的区别

定义线程池对象

public class SingletonThreadPool {
    //核心线程参数
    private static final int CORE_POOL_SIZE = 10;
    //最大线程数
    private static final int MAXIMUM_POOL_SIZE = 50;
    //时间
    private static final long KEEP_ALIVE_TIME = 3;
    //时间单位
    private static final TimeUnit UNIT = TimeUnit.MINUTES;
    //工作队列
    private static final BlockingQueue<Runnable> WORK_QUEUE = new ArrayBlockingQueue<>(50);
    //对象
    private static final ThreadPoolExecutor EXECUTOR;

    // 私有构造器,防止外部通过new创建实例
    private SingletonThreadPool() {
    }

    // 静态初始化块,创建线程池实例
    static {
        EXECUTOR = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_TIME, UNIT, WORK_QUEUE,
                new ThreadPoolExecutor.CallerRunsPolicy());
    }

    // 提供全局访问点获取线程池实例
    public static ThreadPoolExecutor getExecutor() {
        return EXECUTOR;
    }
}

Service层

@Transactional
    public synchronized String createDataCenter(DataCenterSaveReqVO createReqVO) {
        createReqVO.setId(IdUtil.getSnowflakeNextIdStr());
        // 插入
        DataCenterDO dataCenter = BeanUtils.toBean(createReqVO, DataCenterDO.class);
        //创建Runable类
        ThreadPoolExecutor executor = SingletonThreadPool.getExecutor();
        //发送
        executor.execute(new AlarmDataCheck(alarmSettingMapper,alarmDataMapper,dataCenter,dataCenterMapper,alarmDataProcessingMapper,partInfoMapper));
        // 返回
        return dataCenter.getId();
    }

为什么要使用

executor.execute(); 没有返回值,因为线程对象对该方法的返回值设置为void,而且如果方法中抛出的异常,也不会终止当前方法,他的传入对象也必须为Runable或者实现了Runable的对象;
executor.submit(); 有返回值,其中对象必须是且Callable才行,或者实现了Callable的对象才可以;

很多人没搞懂,为什么可以传入对象,现在甚至很多人对忘记了,匿名内部类的使用

executor.execute(new Runnable() {
           @Override
           public void run() {
               
           }
       });

反而现在使用了Lambda,都忘记了里面传入的是什么对象

executor.execute(()->{});

其实在这里系统会默认给你匹配,是Runable还是Callable对象

但是,我这里直接传入了一个实现了Runable的对象,为什么呢,因为这样所有的逻辑都存在一个对象中,更加易于维护和拓展

@Component
@NoArgsConstructor
@Scope("prototype")
public class AlarmDataCheck implements Runnable{
    
    public AlarmDataCheck(AlarmSettingMapper alarmSettingMapper,
                          AlarmDataMapper alarmDataMapper,
                          DataCenterDO dataCenter,
                          DataCenterMapper dataCenterMapper,
                          AlarmDataProcessingMapper alarmDataProcessingMapper,
                          PartInfoMapper partInfoMapper) {
        this.alarmSettingMapper = alarmSettingMapper;
        this.alarmDataMapper = alarmDataMapper;
        this.dataCenter = dataCenter;
        this.dataCenterMapper = dataCenterMapper;
        this.alarmDataProcessingMapper = alarmDataProcessingMapper;
        this.partInfoMapper = partInfoMapper;
    }

    //通过有参构造像alarmSettingDO传入对象
    @Override
    public void run() {
        dataCenterMapper.insert(dataCenter);
        if (warningChecks(dataCenter)){
            dataCenter.setReserveTwo(alarmSettingDO.getReserveOne()).setIsAlarming("1");
            dataCenterMapper.updateById(dataCenter);
        }
        //先获取传感器id,根据传感器id查询
        PartInfoDO partInfoDO = partInfoMapper.selectOne(PartInfoDO::getSensorId, dataCenter.getReserveOne());
        partInfoDO.setState(alarmSettingDO == null ?"0":"3".equals(alarmSettingDO.getReserveOne())?"4":alarmSettingDO.getReserveOne());
        //更新部件磨损状态
        partInfoMapper.updateById(partInfoDO);
    }

在这里由于线程池的启动太快原因导致无法自动注入,我采取了有参构造的方法,我试过懒加载不好使,如果大家,有什么好的方法,欢迎提供

以下是submit的使用教程,以及对应的方法,我的建议是根据情况选择是否要采用submit方法,因为他可以校验线程池中的任务是否执行完毕

  • 11
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值