【问题标题】:Java smart locking mechanismJava 智能锁机制
【发布时间】:2017-12-26 07:20:10
【问题描述】:

我有一些代码需要以非常智能的方式锁定。 假设我需要锁定一个代码部分,该部分执行一些基本上更新一些文本文件的 http 请求。

此操作可以按文件名作用于给定文件。

我的伪代码:

public void UpdateFile(int id){
     dal.invokeHTTPutRequest(id, fileContent);
}

我希望此代码以某种方式同步/锁定

  1. 锁定只会发生在给定的 id 上。因此,如果请求了 id 1,然后又请求了对 id 1 的另一个请求,它将等待。但是如果对 id 2 的请求将到达,它不会等待。

  2. 我想要一些超时,所以如果有很多请求到达并且需要很长时间,他们就会得到一个异常。

有什么想法吗?

【问题讨论】:

    标签: java


    【解决方案1】:

    嗯,在数据库或缓存(如redis)或其他一些仲裁中间件(如zookeeper和ETCD)实现的分布式锁中很常见

    这里提供一个简单的实现,无需其他基于Guava的中间件:

    导入 com.google.common.cache.*;

    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class LockUtil {
        private static final LoadingCache<Integer, Lock> lockCache = CacheBuilder.newBuilder().maximumSize(Long.MAX_VALUE).build(new CacheLoader<Integer, Lock>()
                {
                    @Override
                    public Lock load(Integer i)
                    {
                        return new ReentrantLock();
                    }
                });
    
        public static Lock getLock(int id) throws ExecutionException {
            return lockCache.get(id);
        }
    }
    

    你可以使用 ConcurrentHashMap 代替;

    对于超时,你可以使用 tryLock(timeout) 代替 lock()

    【讨论】:

      【解决方案2】:

      一个简单的解决方案是使用 java ReentrantLock 的 HashMap。在 hashmap 中,您可以使用文件 if 作为检索相关重入锁的键。

      【讨论】:

        【解决方案3】:

        我尝试使用字符串池来获取同步的监控对象。对我来说似乎没问题,请评论这个实现

          import java.util.*;
          import java.util.concurrent.*;
        
          public class Test {
        
            public static void main(String[] args) throws IOException, InterruptedException, ExecutionException {
                  List<Callable<String>> taskList = new ArrayList<>();
                  taskList.add(() -> abcd(1));
                  taskList.add(() -> abcd(3));
                  taskList.add(() -> abcd(1));
                  taskList.add(() -> abcd(1));
                  ExecutorService executor = Executors.newFixedThreadPool(4);
                  executor.invokeAll(taskList);
                }
        
                private static String abcd(int id) throws InterruptedException {
                  synchronized (String.valueOf(id).intern()){
                    System.out.println(id +" - "+Thread.currentThread().getId());
                    Thread.sleep(2000l);
                  }
                  return String.valueOf(id);
                }
        
          } 
        

        希望你可以这样使用

            public void UpdateFile(int id) {
              synchronized (String.valueOf(id).intern()) {
                dal.invokeHTTPutRequest(id, fileContent);
              }
            }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-09-09
          相关资源
          最近更新 更多