定時任務:
@Scheduled(cron= "0 39 3 * * *") public void getAllUnSignData(){ //檢查任務鎖,若其它節點的相同定時任務已經執行,則該節點的任務執行一個空任務,否則設置鎖並執行該任務 String timerName = this.getClass().getName()+Thread.currentThread() .getStackTrace()[1].getMethodName();//當前類名+當前方法名 if(redisLock.requireLock(timerName,7200)){ return; } long startTime = System.currentTimeMillis(); logger.info("定時任務 UnSignStatistics start-->" + startTime ); //找出簽到異常的學生,保存在表中 gxyWarnService.saveUnSignWarn(); long endTime = System.currentTimeMillis(); logger.info("定時任務 UnSignStatistics end-->" +endTime+ ", execute time: " + (endTime - startTime) + "ms" ); }
用類名+方法名作為key, 去redis 獲取鎖。
如果獲取到了鍵值對: (key , 1) ,則說明定時任務已被執行,返回true , 執行if 中的return, 不執行 后面的定時任務。
如果沒有獲取到 鍵值對: (key , 1) ,則說明定時任務沒有被執行 。在redis中 設置鍵值對 (key , 1), (並設置有效期7200秒,這個有效期小於定時任務的周期即可),並返回false 。不執行if 中的return,繼續執行后面的定時任務代碼。
@Component public class RedisLock { //redis中存任務鎖的key前綴 public final static String MOGUDING_TIMER_LOCK_KEY = "com:lock:job:"; @Autowired private RedisTemplate<String, Object> redisTemplate; /** * 判斷是否有鎖。有,返回true;否,返回false,設置一定期效的鎖 * @param lockName * @param expire 鎖的有效時間長,單位:秒 * @return */ public boolean requireLock(String lockName,long expire){ String key = MOGUDING_TIMER_LOCK_KEY+lockName; if(redisTemplate.opsForValue().getAndSet(key,"1")==null){ //“1”這里無任何意義 redisTemplate.expire(key,expire,TimeUnit.SECONDS); return false; }else { return true; } } /** * 判斷是否有鎖。有,返回true;否,返回false,設置一定期效的鎖 * @param lockName * @param date 鎖的有效時間截止點 * @return */ public boolean requireLock(String lockName,Date date){ String key = MOGUDING_TIMER_LOCK_KEY+lockName; if(redisTemplate.opsForValue().getAndSet(key,"1")==null){ //“1”這里無任何意義 redisTemplate.expireAt(key,date); return false; }else { return true; } } }