简体   繁体   English

如何使用锁包装器进行自动关闭?

[英]How to use lock wrapper for autocloseable?

I have wrote following wrapepr: 我写了以下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();
    }
} 

In my code I use it like this: 在我的代码中,我像这样使用它:

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);
        }
    }
    ...
}

I don't want to create wrapper in each method. 我不想在每种方法中创建包装器。

Is there way to combine single wrapper and try with resources ? 有没有办法结合单个包装器并尝试使用资源?

You can use a factory method that returns a singleton. 您可以使用返回单例的工厂方法。 Nothing is forcing you to use a constructor. 没有什么可以强迫您使用构造函数。

BTW you should not call lock inside the try-block. 顺便说一句,您不应该在try块内调用lock That should have already happened in the "acquire the resource" phase (within the constructor in your current design, inside the factory method in my proposal). 那应该已经在“获取资源”阶段中发生了(在当前设计的构造函数中,在我的建议的工厂方法内部)。

I see that the above note is already posted on the Q&A page where you contributed your wrapper . 我发现上面的注释已经发布在“ 问答”页面上,您在其中进行了包装 The page already has very good content; 该页面已经具有非常好的内容; I advise to study it well. 我建议仔细研究。

You are over-complicating your design. 您使设计过于复杂。 If your AutoCloseableLockWrapper intentionally exposes all operations supported by the underlying Lock , there is no point in making it private and adding delegation methods for each of Lock 's methods. 如果您的AutoCloseableLockWrapper故意公开了基础Lock支持的所有操作,则没有必要将其private并为Lock的每个方法添加委派方法。 You could simply make the Lock reference public to allow its use, or leave it off entirely, as the code which creates the wrapper already has a reference to the Lock . 您可以简单地将Lock引用public以允许其使用,也可以完全不使用它,因为创建包装器的代码已经具有对Lock的引用。

All you want to do, is to support a single operation, unlock , which should be viewed as AutoCloseable . 您要做的就是支持单个操作unlock ,该操作应视为AutoCloseable

A Java 8 solution may look like 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
}

It can be used like: 可以像这样使用:

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

If you worry about the instance creation (usually this is not an issue), you can re-use AutoCloseable s: 如果您担心实例创建(通常这不是问题),则可以重新使用AutoCloseable s:

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

To me, it looks less clear since the lock(); 对我来说,由于lock();看起来不太清楚lock(); and try statements are not syntactically coupled and could be separated by accident. try语句在语法上没有耦合,并且可能会因偶然而分开。 But if the lock has a non-local scope, you could solve this by creating a utility method: 但是,如果锁具有非本地范围,则可以通过创建实用程序方法来解决此问题:

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
    }
}

I think, it's not too hard to back-port this logic into Java 7 code, if needed. 我认为,如果需要的话,将该逻辑回移植到Java 7代码中并不难。

I'd prefer just creating a new lock (not a wrapper around a lock): 我更喜欢只创建一个新的锁(而不是围绕锁的包装器):

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();
    }
  }
}

Use like this: 像这样使用:

private AutoReentrantLock consistencyLock = new AutoReentrantLock();

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

Or a more complicated use case, where you unlock halfway: 或更复杂的用例,在其中途解锁:

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.
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 java.util.concurrent.locks.Lock的AutoCloseable包装中的任何风险? - Any risk in a AutoCloseable wrapper for java.util.concurrent.locks.Lock? 如何将ExecuteService与包含AutoCloseable资源的自定义线程一起使用 - How to use ExecuteService with custom Threads that contain a AutoCloseable resource 在 CompletableFuture 中返回 autocloseable object 并在 whenComplete 中使用它 - Return autocloseable object inside a CompletableFuture and use it in whenComplete 如何为建筑上开放的资源实施自动关闭 - How to implement Autocloseable for resource opened on construction 什么是包装函数以及如何使用它? - what is wrapper function and how to use it? 在 Java 中,如何检查 AutoCloseable.close() 是否已被调用? - In Java, how to check that AutoCloseable.close() has been called? 如何创建一个使用AutoCloseable并且还支持Java 6的库 - How to make a library which uses AutoCloseable and also support Java 6 如何在 Flowable.generate 中使 Files.lines AutoCloseable - How to make Files.lines AutoCloseable in Flowable.generate 如何使用SWT制作自动关闭的定时对话框 - How to make an autocloseable on-timer dialogue box with SWT 如何关闭并行流中使用的本地autocloseable线程? - How do I close a thread local autocloseable used in parallel stream?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM