public final class ReactiveLock extends Object
It is modified from ReactiveSemaphore, optimizing away the intermediate WIP variable.
| Constructor and Description |
|---|
ReactiveLock()
Creates an unfair lock
|
ReactiveLock(boolean fairness)
Creates an instance of
CasLock with the given fairness policy |
| Modifier and Type | Method and Description |
|---|---|
boolean |
isLocked()
Checks whether this lock is locked (or has reached the max lock holders)
|
Mono<Void> |
lock()
Get a
Mono that emits success only after acquiring the lock |
<T> Mono<T> |
lockOnNext(Mono<T> mono)
Try to acquire the lock on the next element before propagating
|
LockHandle |
tryLock()
Immediately requests to hold the lock.
|
Mono<Void> |
tryLock(Duration duration)
Tries to acquire the lock, or stop and propagate a
TimeoutException downstream after
certain duration. |
void |
unlock()
Unlocks
|
<T> Mono<T> |
unlockOnEmpty(Mono<T> mono)
Release the lock with
Mono.switchIfEmpty(Mono) |
<T> Mono<T> |
unlockOnError(Mono<T> mono)
Release the lock with
Mono.doOnError(Consumer) before propagating |
<T> Mono<T> |
unlockOnNext(Mono<T> mono)
Release the lock with
Mono.doOnNext(Consumer) before propagating |
<T> Mono<T> |
unlockOnTerminate(Mono<T> mono)
Release the lock with
Mono.doOnTerminate(Runnable) before propagating |
<T> Flux<T> |
withLock(Supplier<Publisher<T>> scoped)
Automatically acquires the lock, executes the function and unlocks.
|
public ReactiveLock()
public ReactiveLock(boolean fairness)
CasLock with the given fairness policyfairness - true if this lock should use a fair ordering policypublic LockHandle tryLock()
Lock
See LockHandle. Subscribe to LockHandle.mono() to get informed
when the lock becomes available.
To properly unlock, you are suggested to handle all cases including completing
without error, failing with errors or the whole Mono or Flux getting
cancelled. You might want to use Lock.withLock(Supplier) to save yourself from
the boilerplate, which internally uses Flux.using(Callable, Function, Consumer)
to LockHandle.cancel() or Lock.unlock() accordingly.
public boolean isLocked()
LockYou should not rely on the result of this due to possible concurrent operations.
public void unlock()
LockUsage:
Lock lock = new ReactiveLock(); /* Or other locks */
mono
.transform(lock::lockOnNext)
.flatMap(item -> {
/* Some processing */
lock.unlock();
return Mono.just(item);
})
.block();
public Mono<Void> tryLock(Duration duration)
LockTimeoutException downstream after
certain duration.public Mono<Void> lock()
LockMono that emits success only after acquiring the lockpublic <T> Flux<T> withLock(Supplier<Publisher<T>> scoped)
Lock
It handles all cases including when the Flux completes without error (empty or not),
fails with errors, or gets cancelled middle way.
public <T> Mono<T> lockOnNext(Mono<T> mono)
LocklockOnNext in interface LockT - the generic type of Monomono - the Mono, of which the next value will require locking to propagateMonopublic <T> Mono<T> unlockOnTerminate(Mono<T> mono)
LockMono.doOnTerminate(Runnable) before propagatingunlockOnTerminate in interface LockT - the generic type of Monomono - the Mono, of which the termination signal will require unlocking to propagateMonopublic <T> Mono<T> unlockOnNext(Mono<T> mono)
LockMono.doOnNext(Consumer) before propagatingunlockOnNext in interface LockT - the generic type of Monomono - the Mono, of which the next value will require unlocking to propagateMonopublic <T> Mono<T> unlockOnEmpty(Mono<T> mono)
LockMono.switchIfEmpty(Mono)unlockOnEmpty in interface LockT - the generic type of Monomono - the Mono, of which the signal, when Mono is empty, will require unlocking to propagateMonopublic <T> Mono<T> unlockOnError(Mono<T> mono)
LockMono.doOnError(Consumer) before propagatingunlockOnError in interface LockT - the generic type of Monomono - the Mono, of which the next error will require unlocking to propagateMono