java定时器及利用redis加锁应对分布式

1、利用spring编写定时任务

@Component
@Configurable
@EnableScheduling //关键注解  
public class TimerScheduler {
   @Scheduled(cron = "0 0 0-23 * * ?") //时间表达式,每天整点执行
   public void emailPushByCron(){
      System.out.printIn(“定时任务”);
   }
}

2、利用javaScheduledExecutorService

@Component
public class TimerUtil {
   Private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

   @PostConstruct   //项目启动便调用
   public void PostConstruct() {
      final Runnable beeper = new Runnable() {
         public void run() {
            System.out.println(“定时任务”);
         }
      };
   scheduler.scheduleAtFixedRate(beeper, 10, 60 * 60, SECONDS);
   }
}

3、Redis用于分布式锁

实现思想:

· 获取锁的时候,创建一个key值加锁,并使用expire命令为锁添加一个超时时间,超过该时间则自动释放锁,锁的value值为机器ip,通过此可以判断出锁是被谁创建的。

· 释放锁的时候,通过ip判断是不是该锁,若是该锁,则执行delete进行锁释放。

实例如下:

@Component
@Configurable
@EnableScheduling
public class TimerScheduler {

    private static final String LOCK_SUCCESS = "OK";
    private static final Long RELEASE_SUCCESS = 1L;
    private static final long DEFAULT_EXPIRE = 20000;//超时时间 20s

    @Autowired
    RedisRepository redisRepository

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

@Scheduled(cron = "0 0 0-23 * * ?")
public void emailPushByCron() {
  String ip = this.getAddressIp(); // 获取本机ip
  String key = "lock-scheduler";
  /**
   * redisRepository.set(key, ip, nxxx, expx, time)
   * key:我们使用key来当锁,保持整个项目是唯一的 
   * ip:value值,表明当前占用锁的是哪一台机器
   * nxxx:我们填的是NX,即当key不存在时,我们进行set操作;若key已经存在,则不做任何操作
   * expx:我们传的是PX,意思是我们要给这个key加一个过期的设置,具体时间由第五个参数决定 
   * time:过期时间
   */
   String result = redisRepository.set(key, ip, "NX", "PX", DEFAULT_EXPIRE);
   if (LOCK_SUCCESS.equals(result)) {// 拿到锁,拥有执行权限
     try {
       logger.info("start execute...");
       System.out.println(“定时任务”);
       logger.info("scheduler finished...");
     } finally { // 释放锁
        // 定义Lua脚本代码,确保操作是原子性的,获取锁对应的value值,检查是否与ip相等,如果相等则删除锁
         String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
         // jedis.eval()方法,执行Lua脚本,使参数KEYS[1]赋值为key,ARGV[1]赋值为ip
         Object unlockResult = redisRepository.eval(script, Collections.singletonList(key), Collections.singletonList(ip));
         if (RELEASE_SUCCESS.equals(unlockResult)) {
             logger.info("unlock success...");
         } else {
             logger.info("unlock failed...");
         }
     }
  } else { // 没拿到锁
     // 查看当前锁是被谁占用
     String lockIp = redisRepository.get(key);
     logger.info("scheduler lock ip : {}", lockIp);
  }
}

//获取ip地址
private String getAddressIp() {
  try {
    InetAddress addr = InetAddress.getLocalHost();
    String ip = addr.getHostAddress().toString(); // 获取本机ip
    return ip;
  } catch (Exception e) {
    // TODO: handle exception
    return null;
  }
}
    原文作者:java锁
    原文地址: https://blog.csdn.net/xi_nuo/article/details/80255646
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞