A Java DSL for synchronizing asynchronous operations
—
Specialized support for waiting on atomic variable changes with built-in matchers and type-safe operations.
Wait for atomic integer values to meet specific conditions.
/**
* Wait until AtomicInteger value matches condition
* @param atomic the AtomicInteger to monitor
* @param matcher Hamcrest matcher for the integer value
* @return final integer value when condition is met
*/
Integer untilAtomic(AtomicInteger atomic, Matcher<? super Integer> matcher);/**
* Wait until AtomicInteger value passes consumer assertion
* @param atomic the AtomicInteger to monitor
* @param matcher consumer that performs assertions on the value
*/
void untilAtomic(AtomicInteger atomic, Consumer<? super Integer> matcher);AtomicInteger Examples:
AtomicInteger counter = new AtomicInteger(0);
// Wait for counter to reach threshold using matcher
Integer finalValue = await().untilAtomic(counter, greaterThanOrEqualTo(10));
// Wait for counter using multiple conditions
await().untilAtomic(counter, allOf(greaterThan(5), lessThan(20)));
// Wait using consumer assertion
await().untilAtomic(counter, value -> {
assertThat(value).isGreaterThan(0);
assertThat(value % 2).isEqualTo(0); // Even number
});
// Wait for specific value
await().untilAtomic(counter, equalTo(42));Wait for atomic long values to meet specific conditions.
/**
* Wait until AtomicLong value matches condition
* @param atomic the AtomicLong to monitor
* @param matcher Hamcrest matcher for the long value
* @return final long value when condition is met
*/
Long untilAtomic(AtomicLong atomic, Matcher<? super Long> matcher);/**
* Wait until AtomicLong value passes consumer assertion
* @param atomic the AtomicLong to monitor
* @param matcher consumer that performs assertions on the value
*/
void untilAtomic(AtomicLong atomic, Consumer<? super Long> matcher);AtomicLong Examples:
AtomicLong timestamp = new AtomicLong(0);
// Wait for timestamp to be set
Long finalTimestamp = await().untilAtomic(timestamp, greaterThan(0L));
// Wait for timestamp to be recent
await().untilAtomic(timestamp,
greaterThan(System.currentTimeMillis() - Duration.ofMinutes(1).toMillis()));
// Wait using consumer assertion for complex validation
await().untilAtomic(timestamp, value -> {
assertThat(value).isGreaterThan(startTime);
assertThat(value).isLessThanOrEqualTo(System.currentTimeMillis());
});
// Wait for specific milestone
AtomicLong totalBytes = new AtomicLong(0);
await().atMost(30, SECONDS)
.untilAtomic(totalBytes, greaterThanOrEqualTo(1_000_000L)); // 1MBWait for atomic boolean values and state changes.
/**
* Wait until AtomicBoolean value matches condition
* @param atomic the AtomicBoolean to monitor
* @param matcher Hamcrest matcher for the boolean value
*/
void untilAtomic(AtomicBoolean atomic, Matcher<? super Boolean> matcher);/**
* Wait until AtomicBoolean value passes consumer assertion
* @param atomic the AtomicBoolean to monitor
* @param matcher consumer that performs assertions on the value
*/
void untilAtomic(AtomicBoolean atomic, Consumer<? super Boolean> matcher);/**
* Wait until AtomicBoolean becomes true
* @param atomic the AtomicBoolean to monitor
*/
void untilTrue(AtomicBoolean atomic);
/**
* Wait until AtomicBoolean becomes false
* @param atomic the AtomicBoolean to monitor
*/
void untilFalse(AtomicBoolean atomic);AtomicBoolean Examples:
AtomicBoolean isReady = new AtomicBoolean(false);
AtomicBoolean isProcessing = new AtomicBoolean(true);
// Convenience methods for common cases
await().untilTrue(isReady);
await().untilFalse(isProcessing);
// Using matchers
await().untilAtomic(isReady, equalTo(true));
await().untilAtomic(isProcessing, equalTo(false));
// Using consumer assertions
await().untilAtomic(isReady, ready -> {
assertThat(ready).isTrue();
// Additional checks can be performed here
});
// Combined with timeout and polling
await().atMost(5, SECONDS)
.pollInterval(100, MILLISECONDS)
.untilTrue(systemInitialized);Wait for atomic reference values and object state changes.
/**
* Wait until AtomicReference value matches condition
* @param atomic the AtomicReference to monitor
* @param matcher Hamcrest matcher for the reference value
* @return final reference value when condition is met
*/
<V> V untilAtomic(AtomicReference<V> atomic, Matcher<? super V> matcher);/**
* Wait until AtomicReference value passes consumer assertion
* @param atomic the AtomicReference to monitor
* @param matcher consumer that performs assertions on the value
*/
<V> void untilAtomic(AtomicReference<V> atomic, Consumer<? super V> matcher);AtomicReference Examples:
AtomicReference<String> status = new AtomicReference<>();
AtomicReference<List<String>> results = new AtomicReference<>();
AtomicReference<ConnectionState> connectionState = new AtomicReference<>();
// Wait for reference to be set
String finalStatus = await().untilAtomic(status, notNullValue());
// Wait for specific value
await().untilAtomic(status, equalTo("COMPLETED"));
// Wait for reference with complex object conditions
await().untilAtomic(results, hasSize(greaterThan(0)));
// Wait using consumer assertions
await().untilAtomic(connectionState, state -> {
assertThat(state).isNotNull();
assertThat(state.isConnected()).isTrue();
assertThat(state.getLatency()).isLessThan(Duration.ofMillis(100));
});
// Wait for enum state change
await().untilAtomic(connectionState,
state -> state == ConnectionState.ESTABLISHED);
// Complex reference conditions
AtomicReference<Map<String, Object>> configuration = new AtomicReference<>();
await().untilAtomic(configuration, config -> {
assertThat(config).isNotNull();
assertThat(config).containsKey("database.url");
assertThat(config).containsKey("api.key");
assertThat(config.size()).isGreaterThan(5);
});Patterns for testing concurrent operations with atomic variables.
// Producer thread updates counter
AtomicInteger itemsProduced = new AtomicInteger(0);
AtomicInteger itemsConsumed = new AtomicInteger(0);
// Wait for producer to generate items
await().untilAtomic(itemsProduced, greaterThanOrEqualTo(100));
// Wait for consumer to process items
await().untilAtomic(itemsConsumed, greaterThanOrEqualTo(50));
// Wait for production/consumption balance
await().until(() -> {
int produced = itemsProduced.get();
int consumed = itemsConsumed.get();
return produced > 0 && consumed >= produced / 2;
});AtomicInteger stage1Complete = new AtomicInteger(0);
AtomicInteger stage2Complete = new AtomicInteger(0);
AtomicBoolean pipelineReady = new AtomicBoolean(false);
// Wait for pipeline stages
await().untilAtomic(stage1Complete, greaterThanOrEqualTo(100));
await().untilAtomic(stage2Complete, greaterThanOrEqualTo(50));
await().untilTrue(pipelineReady);
// Or wait for all stages combined
await().until(() ->
stage1Complete.get() >= 100 &&
stage2Complete.get() >= 50 &&
pipelineReady.get());AtomicInteger activeConnections = new AtomicInteger(0);
AtomicInteger availableConnections = new AtomicInteger(10);
// Wait for connections to be available
await().untilAtomic(availableConnections, greaterThan(0));
// Wait for load to decrease
await().untilAtomic(activeConnections, lessThan(5));
// Wait for pool to stabilize
await().until(() -> {
int active = activeConnections.get();
int available = availableConnections.get();
return active + available == 10; // Total pool size
});Install with Tessl CLI
npx tessl i tessl/maven-org-awaitility--awaitility