我写了以下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);
}
}
...
}
我不想在每个方法中创建包装器。
有没有办法结合单个包装器并尝试使用资源?
答案 0 :(得分:1)
您可以使用返回单例的工厂方法。没有什么是强迫你使用构造函数。
顺便说一句,你不应该在try-block中调用lock
。这应该已经发生在"获取资源"阶段(在当前设计的构造函数内,在我的提议中的工厂方法内)。
我看到上面的注释已经发布在Q&A page where you contributed your wrapper上了。该页面已经有很好的内容;我建议好好研究它。
答案 1 :(得分:1)
您的设计过于复杂。如果您的AutoCloseableLockWrapper
故意公开基础Lock
支持的所有操作,则无需为private
添加Lock
并为每个Lock
方法添加委派方法。您可以简单地使public
引用Lock
允许其使用,或者完全不使用它,因为创建包装器的代码已经引用了unlock
。
您要做的只是支持单个操作AutoCloseable
,该操作应被视为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
}
。
Java 8解决方案可能看起来像
Lock lock=…
// …
try(AutoUnlock u=AutoUnlock.lock(lock)) {
// critical code
}
// …
try(AutoUnlock u=AutoUnlock.lock(lock)) {
// critical code
}
可以像:
一样使用AutoCloseable
如果您担心实例创建(通常这是不问题),您可以重新使用AutoUnlock reusable=lock::unlock;
// …
lock.lock();
try(AutoUnlock u=reusable) {
// critical code
}
// …
lock.lock();
try(AutoUnlock u=reusable) {
// critical code
}
s:
lock();
对我来说,它看起来不太清楚,因为try
和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
}
}
语句没有语法耦合,可能会意外分开。但是如果锁具有非局部范围,则可以通过创建实用程序方法来解决此问题:
with open('grades.txt') as f:
print(Counter(f.read()))
我认为,如果需要,将此逻辑反向移植到Java 7代码中并不太难。
答案 2 :(得分: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.
}