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?

+3


source to share


1 answer


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!

+1


source







All Articles