0

次のwrapeprを書きました:

public class AutoCloseableLockWrapper implements AutoCloseable, Lock{
    private final Lock lock;
    public AutoCloseableLockWrapper(Lock l) {
        this.lock = l;
    }
    @Override
    public void lock() {
        this.lock.lock();
    }

    @Override
    public void lockInterruptibly() throws InterruptedException {
        lock.lockInterruptibly();
    }

    @Override
    public boolean tryLock() {
        return lock.tryLock();
    }

    @Override
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
        return lock.tryLock(time,unit);
    }

    @Override
    public void unlock() {
        lock.unlock();
    }

    @Override
    public Condition newCondition() {
        return lock.newCondition();
    }
    @Override
    public void close() {
        this.lock.unlock();
    }
} 

私のコードでは、次のように使用します。

public class ReadWriteMap implements Map {

    private HashMap map = new HashMap();
    private ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
    private Lock readLock = readWriteLock.readLock();
    private Lock writeLock = readWriteLock.writeLock();

    @Override
    public int size() {
        try (AutoCloseableLockWrapper autoCloseableLockWrapper = new AutoCloseableLockWrapper(readLock)) {
            autoCloseableLockWrapper.lock();
            return map.size();
        }

    }

    @Override
    public boolean isEmpty() {
        try (AutoCloseableLockWrapper autoCloseableLockWrapper = new AutoCloseableLockWrapper(readLock)) {
            autoCloseableLockWrapper.lock();
            return map.isEmpty();
        }
    }

    @Override
    public boolean containsKey(Object key) {
        try (AutoCloseableLockWrapper autoCloseableLockWrapper = new AutoCloseableLockWrapper(readLock)) {
            autoCloseableLockWrapper.lock();
            return map.containsKey(key);
        }
    }
    ...
}

各メソッドでラッパーを作成したくありません。

単一のラッパーを組み合わせてリソースで試す方法はありますか?

4

3 に答える 3

1

設計を過度に複雑にしています。AutoCloseableLockWrapper基になる でサポートされているすべての操作を意図的に公開している場合、それを作成して の各メソッドに委譲メソッドを追加Lockしても意味がありません。ラッパーを作成するコードにはすでに.privateLockLockpublicLock

やりたいことは、単一の操作 をサポートすることだけです。unlockこれは、 として表示されAutoCloseableます。

Java 8 ソリューションは次のようになります。

import java.util.concurrent.locks.Lock;

public interface AutoUnlock extends AutoCloseable {
    public static AutoUnlock lock(Lock lock) {
        lock.lock();
        return lock::unlock;
    }

    @Override
    public void close(); // no checked exceptions
}

次のように使用できます。

Lock lock=…
// …
try(AutoUnlock u=AutoUnlock.lock(lock)) {
    // critical code
}
// …
try(AutoUnlock u=AutoUnlock.lock(lock)) {
    // critical code
}

インスタンスの作成が心配な場合 (通常、これは問題ではありません)、sを再利用できます。AutoCloseable

AutoUnlock reusable=lock::unlock;
// …
lock.lock();
try(AutoUnlock u=reusable) {
    // critical code
}
// …
lock.lock();
try(AutoUnlock u=reusable) {
    // critical code
}

lock();andtryステートメントは構文的に結合されておらず、偶然に分離される可能性があるため、私にはあまり明確ではないように見えます。しかし、ロックのスコープがローカルではない場合、ユーティリティ メソッドを作成することでこれを解決できます。

final Lock lockInstance; // this field name is to prevent confusion with the lock() method
final AutoUnlock reusable;

YourConstructor(Lock lock) {// you may get the Lock as a parameter
    lockInstance=lock; // or create one here, right in the constructor
    reusable=lockInstance::unlock;
}

AutoUnlock lock() {
    lockInstance.lock();
    return reusable;
}
void doSomething() {
    // …
    try(AutoUnlock u=lock()) {
        // critical code
    }
    // …
    try(AutoUnlock u=lock()) {
        // critical code
    }
}

必要に応じて、このロジックを Java 7 コードにバックポートすることはそれほど難しくないと思います。

于 2015-09-29T18:20:53.860 に答える
0

新しいロックを作成するだけのほうがいいと思います(ロックのラッパーではありません):

public class AutoReentrantLock implements AutoCloseable {
  private final ReentrantLock lock = new ReentrantLock();

  public AutoReentrantLock lock() {
    lock.lock();

    return this;
  }

  public void earlyUnlock() {
    lock.unlock();
  }

  @Override
  public void close() {
    if(lock.isHeldByCurrentThread()) {
      lock.unlock();
    }
  }
}

次のように使用します。

private AutoReentrantLock consistencyLock = new AutoReentrantLock();

try(AutoReentrantLock lock = consistencyLock.lock()) {
  // other code
}

または、途中でロックを解除する、より複雑な使用例:

private AutoReentrantLock consistencyLock = new AutoReentrantLock();

try(AutoReentrantLock lock = consistencyLock.lock()) {
  // Place code here that gathers information (while under lock)        
  // but may exit early or throw exceptions

  lock.earlyUnlock();

  // ... followed by code that is slow that acts upon above gathered information.
}
于 2019-04-02T08:31:06.303 に答える