spring-boot定时任务执行多线程

1.定时任务配置类

主要实现了SchedulingConfigurer接口,要重写configureTasks方法

@Configuration
@EnableScheduling
public class ScheduleConfig implements SchedulingConfigurer {
    public static final Logger LOGGER = LoggerFactory.getLogger(ScheduleConfig.class);
    /**
     * Redis
     */
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private IDeviceService deviceService;

    @Autowired
    private IDeviceDataService deviceDataService;

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        // 心跳检测定时模块
        taskRegistrar.addTriggerTask(new CheckHeartRunnable(stringRedisTemplate, deviceService), new Trigger() {
            @Override
            public Date nextExecutionTime(TriggerContext triggerContext) {
                //Constants.deviceAckCheckCron = "0/5 * * * * ?"
                CronTrigger trigger = new CronTrigger(Constants.deviceHeartCheckCron);
                Date nextExec = trigger.nextExecutionTime(triggerContext);
                return nextExec;
            }
        });
}

2.任务类:执行设备心跳检测

这个类实现了Runnable接口,执行定时任务时,就开了一个线程.

package com.polycis.ns2g.domain.schedule.runnable;

import com.polycis.ns2g.comment.MapConfigurator;
import com.polycis.ns2g.config.PropertyConf;
import com.polycis.ns2g.domain.entity.DataEntity;
import com.polycis.ns2g.domain.entity.DeviceEntity;
import com.polycis.ns2g.domain.service.IDeviceService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.StringRedisTemplate;

import java.util.Date;
import java.util.Map;

import static com.polycis.ns2g.comment.Constants.deviceTimeOut;
import static com.polycis.ns2g.comment.Constants.getaWayTimeOut;
import static com.polycis.ns2g.comment.MapConfigurator.*;
import static com.polycis.ns2g.comment.MapConfigurator.CHANNEL_ENTITY_MAP;
import static com.polycis.ns2g.comment.MapConfigurator.DEVICE_HEART_DATA;

public class CheckHeartRunnable implements Runnable {

    public static final Logger LOGGER = LoggerFactory.getLogger(CheckHeartRunnable.class);

    private StringRedisTemplate stringRedisTemplate;

    private IDeviceService deviceService;

    public CheckHeartRunnable(StringRedisTemplate stringRedisTemplate, IDeviceService deviceService){
        this.stringRedisTemplate = stringRedisTemplate;
        this.deviceService = deviceService;
    }

    /**
     * 该方法用来检测内存中心跳停止了的设备,并清除设备对应的数据信息
     */
    @Override
    public void run() {
//        LOGGER.info("================= 设备心跳检测功能定时模块启动 =================");
        // 定时检测硬件心跳数据
        // 检测当前系统中是否存在超时未上报心跳的设备
        checkHeart(DEVICE_HEART_DATA, deviceTimeOut);
        // 检测当前系统中是否存在超时未上报心跳的网关
        checkHeart(GETAWAY_HEART_DATA, getaWayTimeOut);
    }

    private void checkHeart(Map<String, Date> heartDate, Integer devTimeOut){
        long now = System.currentTimeMillis();
        long time;
        Integer pattern;
        Integer timeOut;
        for (Map.Entry<String, Date> entry : heartDate.entrySet()){
            pattern = MapConfigurator.DEVICE_FOR_PATTERN.get(entry.getKey());

            if (pattern == null){
                String patString = stringRedisTemplate.opsForValue().get(entry.getKey() +
                        PropertyConf.config.getProperty("redis.device.pattern.suffix"));
                if (patString == null) {
                    time = now - (devTimeOut * 1000);
                }else {
                    pattern = Integer.valueOf(patString);
                    timeOut = MapConfigurator.CONFIG_FOR_PATTERN.get(pattern);
                    if (timeOut == null){
                        time = now - (devTimeOut * 1000);
                    }else{
                        time = now - (timeOut * 1000);
                        System.out.println("设备属于模式:" + pattern + ", 超时时间为:" + timeOut + "秒");
                    }
                }
            }else{
                timeOut = MapConfigurator.CONFIG_FOR_PATTERN.get(pattern);
                if (timeOut == null){
                    time = now - (devTimeOut * 1000);
                }else{
                    time = now - (timeOut * 1000);
                    System.out.println("设备属于模式:" + pattern + ", 超时时间为:" + timeOut + "秒");
                }
            }


            if (entry.getValue() != null && entry.getValue().getTime() < time){
                // 该设备在指定的时间内没有更新内存中的心跳数据,则检测是否有在redis中更新心跳
                String strHeartTime = stringRedisTemplate.opsForValue().get(entry.getKey() +
                        PropertyConf.config.getProperty("redis.heart.suffix"));
                if (strHeartTime == null || Long.valueOf(strHeartTime) < time){
                    // 设备同时在内存和redis中都没有数据心跳,可判断发生故障,向AS推送故障信息
                    DataEntity dataEntity = new DataEntity();
                    dataEntity.setDeviceEntity(new DeviceEntity());
                    dataEntity.getDeviceEntity().setDevUID(entry.getKey());
                    dataEntity.setType(Integer.valueOf(PropertyConf.config.getProperty("server.data.fault")));

                    DeviceEntity deviceEntity = new DeviceEntity();
//                    deviceEntity.setNsServerEntity(ServerRegiste.nsServerEntity);
                    deviceEntity.setDevUID(dataEntity.getDeviceEntity().getDevUID());
                    deviceEntity.setStatus(3);
                    try {
                        deviceService.deviceJoin(deviceEntity);
                        // TODO 向AS推送设备故障消息(暂定无需推送)
//                        RabbitMQUtil.sendMessage(JsonUtil.toJson(deviceEntity), PropertyConf.config.getProperty("fault.data.pub.queue"));
                    }catch (Exception e){
                        LOGGER.error("系统错误", e);
                    }

                    LOGGER.info("设备" + entry.getKey() + "出现故障!");
                }else {
                    // 设备在内存中没有心跳,而在redis中存在心跳,表示设备已经连接到其他ns服务器,删除本地注册信息以及下发数据信息
                    DEVICE_JOIN_DATA.remove(entry.getKey());
                    WAIT_ACK_DOWN_DATA.remove(entry.getKey());
                    WAIT_DOWN_DATA.remove(entry.getKey());
                    DEVICE_FOR_PATTERN.remove(entry.getKey());
                }
                // 设备在内存中没有心跳,删除本地网络管道、心跳缓存
                UPLOAD_DATA_SPLIT.remove(CHANNEL_ENTITY_MAP.get(entry.getKey()).getChannelHandlerContext());
                CHANNEL_ENTITY_MAP.remove(entry.getKey());
                heartDate.remove(entry.getKey());
            }
        }
    }
}

猜你喜欢

转载自blog.csdn.net/reee112/article/details/86489070