[英]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.