我有原始的同步代码
Lock lock = getLock(userId); // get a lock from guava Striped locks
lock.lock();
try {
// do some database writing action
updateUserByUserId(userId);
return updateUserPropertiesByUserId(userId);
}
finally {
lock.unlock();
}
锁定的目的是模仿更高级别的悲观数据库锁定。
在Java8中,引入了CompleteableFutures。 updateUserByUserId(userId);
和updateUserPropertiesByUserId(userId);
现在可以返回CompletableFuture<Void>
进行完全异步实施。
我的问题是,我如何使用相同的机制?或者这种锁定完全错误的方式? (我真的不想依赖数据库的锁定。如果可能的话,我想在app层而不是数据库层处理这个问题。
我试过了
Lock lock = getLock(userId); // get a lock from guava Striped locks
return CompletableFuture
.supplyAsync(() -> {
lock.lock();
})
.thenCompose(VOID -> updateUserByUserId(userId))
.thenCompose(entity -> updateUserPropertiesByUserId(userId))
.whenComplete((entity, ex) -> {
lock.unlock();
});
但我一直在IllegalMonitorStateException
lock.unlock();
,这是预期的,因为你不应该在另一个线程中解锁。
有什么建议吗?
答案 0 :(得分:1)
您可以为回调的...Async
variants提供执行程序,因此为锁定和解锁的一个回调提供相同的single threaded executor应该确保它们在同一个线程上执行。
Lock lock = getLock(userId); // get a lock from guava Striped locks
Executor lockExecutor = Executors.newSingleThreadExecutor();
return CompletableFuture
.supplyAsync(() -> {
lock.lock();
}, lockExecutor)
.thenCompose(VOID -> updateUserByUserId(userId))
.thenCompose(entity -> updateUserPropertiesByUserId(userId))
.whenCompleteAsync((entity, ex) -> {
lock.unlock();
}, lockExecutor);
注意:我没有运行它,希望它有效!