欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-05-01 17:16:13
...

1.定时任务配置类

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

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

    @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());
            }
        }
    }
}

 

相关标签: 定时任务