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

redis实现多进程数据同步工具代码分享

程序员文章站 2024-02-23 08:26:34
复制代码 代码如下:package com.happyelements.odin.util; import static com.google.common.base.p...

复制代码 代码如下:

package com.happyelements.odin.util;

import static com.google.common.base.preconditions.checknotnull;

import org.jetbrains.annotations.notnull;

import com.happyelements.odin.jedis.jedisclient;
import com.happyelements.rdcenter.commons.util.datetimeutil;

/**
 * user: jude.wang
 * date: 14-1-16
 * time: 上午9:43
 */
public class concurrentutil {

 public static final string user_lock_key_format = "user_lock_%d_%s";
 public static final string custom_lock_format = "custom_lock_%s";
 public static final jedisclient redisclient = jedisclient.getinstance();
 public static final string unlocked = "0";
 public static final string locked = "1";
 private static final int max_repeat_times = 10;

 @notnull
 public static string builduserlockkey(long userid, @notnull string key) {
  checknotnull(key);
  return string.format(user_lock_key_format, userid, key);
 }

 @notnull
 public static string buildcustomlockkey(@notnull string key) {
  checknotnull(key);
  return string.format(custom_lock_format, key);
 }

 /**
  * 此方法可以因为拿不到锁而导致operation没有执行
  *
  * @param key
  * @see com.happyelements.odin.util.concurrentutil#buildcustomlockkey(string)
  * @see com.happyelements.odin.util.concurrentutil#builduserlockkey(long, string)
  *
  * @param operation
  * @throws com.happyelements.odin.util.concurrentutil.operationnotexecexception
  *             operation没有被执行
  */
 public static void dojobwithlock(@notnull string key, @notnull ilockoperation operation) throws operationnotexecexception {

  boolean locked = false;
  try {
   checknotnull(key);
   checknotnull(operation);
   locked = lock(key);

  } catch (throwable t) {
   throw new operationnotexecexception(key, t);
  }

  try {
   if (locked) {
    // system.out.println(thread.currentthread() + "\t" + "lock");
    operation.dojob();
   } else {
    throw new operationnotexecexception(key);
   }
  } finally {
   if (locked) {
    unlock(key);
   }
  }
 }

 private static void unlock(string key) {
  try {
   checknotnull(key);
   string oldstatus = redisclient.getset(key, unlocked);
   if (isunlocked(oldstatus)) {
    // lock->dojob->过期->unlock
    // todo log
   }
  } catch (throwable t) {
   // todo log
  }
  // system.out.println(thread.currentthread() + "\t" + "unlock");
 }

 private static boolean isunlocked(string status) {
  return status == null || status.equals(unlocked);
 }

 private static boolean lock(string key) {

  boolean locked = false;

  for (int i = 0; i < max_repeat_times; i++) {
   string oldstatus = redisclient.getset(key, locked);

   if (isunlocked(oldstatus)) {
    if (oldstatus == null) {
     redisclient.expire(key, datetimeutil.minute_second * 5);
     locked = true;
     break;
    }
    locked = true;
    break;
   }
  }

  return locked;
 }

 public static interface ilockoperation {
  void dojob();
 }

 /**
  * {@link com.happyelements.odin.util.concurrentutil.ilockoperation#dojob()}没有被执行
  * 上层必须处理该异常,捕获到该异常可以retry本次操作,或者包装成{@link com.happyelements.rdcenter.commons.throwable.heexception} 抛出去
  */
 public static class operationnotexecexception extends exception {
  public operationnotexecexception() {
  }

  public operationnotexecexception(string s) {
   super(s);
  }

  public operationnotexecexception(string s, throwable throwable) {
   super(s, throwable);
  }

  public operationnotexecexception(throwable throwable) {
   super(throwable);
  }
 }
}