2017-12-26 6 views
1

私は非常にスマートな方法でロックする必要があるいくつかのコードがあります。 私は基本的にいくつかのテキストファイルを更新するいくつかのhttp要求を行うコードセクションをロックする必要があるとしましょう。Javaのスマートなロック機構

この操作は、指定されたファイルをその名前で操作できます。

私の擬似コード:

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

私は、このコードは、ロックのみ指定したidのために起こるのだろう

  1. ような方法で同期/ロックになりたいです。したがって、id 1が要求され、id 1への別の要求が要求されると、それは待機します。しかし、id 2へのリクエストが到着すると、それは待たないでしょう。

  2. 多くのリクエストが到着すると、タイムアウトが必要なので、多くの時間がかかり、例外が発生します。

答えて

0

単純な解決策は、Java ReentrantLockのHashMapを使用することです。ハッシュマップでは、relaventの再入可能ロックを取得するためのキーとしてファイルを使用できます。

1

まあ、それは(例えばRedisのような)データベースまたはキャッシュによって実装分散ロックまたは他のいくつかの定足数のミドルウェア(例えば飼育係などとETCD)

がここグアバに基づいて他のミドルウェアない単純な実装を提供するで一般的です。

import 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(タイムアウト)の代わりに、ロックを(使用することができます)

0

私は、監視対象を同期取得する文字列プールを試してみました。私のために大丈夫であるように思わ

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); 
     } 
    } 
ように使用することを願って、この実装にコメントしてください