Final Future and Castles
I have original synchronous code,
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();
}
The purpose of the lock is to simulate a pessimistic database lock at a higher level.
Java8 introduced the CompleteableFutures functions. Both updateUserByUserId(userId);
and updateUserPropertiesByUserId(userId);
can now return CompletableFuture<Void>
for a fully asynchronous implementation.
My question is, how can I use the same mechanism? or is this way to block completely? (I don't want to rely on database locking. If possible, I want to handle this in the application layer instead of the database layer)
I tried
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();
});
But I am getting IllegalMonitorStateException
on lock.unlock();
, which is expected because you shouldn't be blocking the lock on another thread.
Any suggestions?
source to share
You can provide the executor with callback ...Async
options , so supplying the same single-threaded executor with a single callback that blocks and unblocks must ensure that they run on the same thread.
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);
NOTE: I haven't run this, hope it works!
source to share