Java : Condition with Examples

Condition (Java SE 19 & JDK 19) API Examples.
You will find code examples on most Condition methods.


Summary

Condition factors out the Object monitor methods (wait, notify and notifyAll) into distinct objects to give the effect of having multiple wait-sets per object, by combining them with the use of arbitrary Lock implementations. Where a Lock replaces the use of synchronized methods and statements, a Condition replaces the use of the Object monitor methods.

Class diagram

final long current = System.nanoTime();
final DoubleSupplier elapsedTime = () -> (System.nanoTime() - current) / 1000000000.0;

try (var executor = Executors.newSingleThreadExecutor()) {
    final var lock = new ReentrantLock();
    final var cond = lock.newCondition();

    executor.submit(() -> {
        System.out.printf("lock ... (%f sec.)%n", elapsedTime.getAsDouble());
        lock.lock();
        try {
            System.out.printf("await ... (%f sec.)%n", elapsedTime.getAsDouble());
            cond.await();
            System.out.printf("await OK! (%f sec.)%n", elapsedTime.getAsDouble());
        } catch (InterruptedException e) {
            System.out.println("InterruptedException!");
        } finally {
            lock.unlock();
        }
    });

    TimeUnit.SECONDS.sleep(5);

    lock.lock();
    try {
        System.out.printf("signal! (%f sec.)%n", elapsedTime.getAsDouble());
        cond.signal();
    } finally {
        lock.unlock();
    }
}

// Result
// ↓
//lock ... (0.003795 sec.)
//await ... (0.006260 sec.)
//signal! (5.019196 sec.)
//await OK! (5.019534 sec.)

Methods

void await ()

Causes the current thread to wait until it is signalled or interrupted.

final long current = System.nanoTime();
final DoubleSupplier elapsedTime = () -> (System.nanoTime() - current) / 1000000000.0;

try (var executor = Executors.newSingleThreadExecutor()) {
    final var lock = new ReentrantLock();
    final var cond = lock.newCondition();

    executor.submit(() -> {
        System.out.printf("lock ... (%f sec.)%n", elapsedTime.getAsDouble());
        lock.lock();
        try {
            System.out.printf("await ... (%f sec.)%n", elapsedTime.getAsDouble());
            cond.await();
            System.out.printf("await OK! (%f sec.)%n", elapsedTime.getAsDouble());
        } catch (InterruptedException e) {
            System.out.println("InterruptedException!");
        } finally {
            lock.unlock();
        }
    });

    TimeUnit.SECONDS.sleep(5);

    lock.lock();
    try {
        System.out.printf("signal! (%f sec.)%n", elapsedTime.getAsDouble());
        cond.signal();
    } finally {
        lock.unlock();
    }
}

// Result
// ↓
//lock ... (0.003795 sec.)
//await ... (0.006260 sec.)
//signal! (5.019196 sec.)
//await OK! (5.019534 sec.)

boolean await (long time, TimeUnit unit)

Causes the current thread to wait until it is signalled or interrupted, or the specified waiting time elapses.

final long current = System.nanoTime();
final DoubleSupplier elapsedTime = () -> (System.nanoTime() - current) / 1000000000.0;

try (var executor = Executors.newSingleThreadExecutor()) {
    final var lock = new ReentrantLock();
    final var cond = lock.newCondition();

    executor.submit(() -> {
        System.out.printf("lock ... (%f sec.)%n", elapsedTime.getAsDouble());
        lock.lock();
        try {
            System.out.printf("await ... (%f sec.)%n", elapsedTime.getAsDouble());

            final var ret = cond.await(2, TimeUnit.SECONDS);
            System.out.printf("await ret = %b (%f sec.)%n", ret, elapsedTime.getAsDouble());
        } catch (InterruptedException e) {
            System.out.println("InterruptedException!");
        } finally {
            lock.unlock();
        }
    });

    TimeUnit.SECONDS.sleep(1);

    lock.lock();
    try {
        System.out.printf("signal! (%f sec.)%n", elapsedTime.getAsDouble());
        cond.signal();
    } finally {
        lock.unlock();
    }
}

// Result
// ↓
//lock ... (0.003034 sec.)
//await ... (0.004681 sec.)
//signal! (1.007004 sec.)
//await ret = true (1.007422 sec.)

An example with timeout.

final long current = System.nanoTime();
final DoubleSupplier elapsedTime = () -> (System.nanoTime() - current) / 1000000000.0;

try (var executor = Executors.newSingleThreadExecutor()) {
    final var lock = new ReentrantLock();
    final var cond = lock.newCondition();

    executor.submit(() -> {
        System.out.printf("lock ... (%f sec.)%n", elapsedTime.getAsDouble());
        lock.lock();
        try {
            System.out.printf("await ... (%f sec.)%n", elapsedTime.getAsDouble());

            final var ret = cond.await(2, TimeUnit.SECONDS);
            System.out.printf("await ret = %b (%f sec.)%n", ret, elapsedTime.getAsDouble());
        } catch (InterruptedException e) {
            System.out.println("InterruptedException!");
        } finally {
            lock.unlock();
        }
    });

    TimeUnit.SECONDS.sleep(3);
}

// Result
// ↓
//lock ... (0.001920 sec.)
//await ... (0.002397 sec.)
//await ret = false (2.015032 sec.)

long awaitNanos (long nanosTimeout)

Causes the current thread to wait until it is signalled or interrupted, or the specified waiting time elapses.

final long current = System.nanoTime();
final DoubleSupplier elapsedTime = () -> (System.nanoTime() - current) / 1000000000.0;

try (var executor = Executors.newSingleThreadExecutor()) {
    final var lock = new ReentrantLock();
    final var cond = lock.newCondition();

    executor.submit(() -> {
        System.out.printf("lock ... (%f sec.)%n", elapsedTime.getAsDouble());
        lock.lock();
        try {
            System.out.printf("await ... (%f sec.)%n", elapsedTime.getAsDouble());

            final var ret = cond.awaitNanos(TimeUnit.SECONDS.toNanos(2));
            System.out.printf("await ret = %d (%f sec.)%n", ret, elapsedTime.getAsDouble());
        } catch (InterruptedException e) {
            System.out.println("InterruptedException!");
        } finally {
            lock.unlock();
        }
    });

    TimeUnit.SECONDS.sleep(1);

    lock.lock();
    try {
        System.out.printf("signal! (%f sec.)%n", elapsedTime.getAsDouble());
        cond.signal();
    } finally {
        lock.unlock();
    }
}

// Result
// ↓
//lock ... (0.002420 sec.)
//await ... (0.003724 sec.)
//signal! (1.003412 sec.)
//await ret = 1000114200 (1.003748 sec.)

An example with timeout.

final long current = System.nanoTime();
final DoubleSupplier elapsedTime = () -> (System.nanoTime() - current) / 1000000000.0;

try (var executor = Executors.newSingleThreadExecutor()) {
    final var lock = new ReentrantLock();
    final var cond = lock.newCondition();

    executor.submit(() -> {
        System.out.printf("lock ... (%f sec.)%n", elapsedTime.getAsDouble());
        lock.lock();
        try {
            System.out.printf("await ... (%f sec.)%n", elapsedTime.getAsDouble());

            final var ret = cond.awaitNanos(TimeUnit.SECONDS.toNanos(2));
            System.out.printf("await ret = %d (%f sec.)%n", ret, elapsedTime.getAsDouble());
        } catch (InterruptedException e) {
            System.out.println("InterruptedException!");
        } finally {
            lock.unlock();
        }
    });

    TimeUnit.SECONDS.sleep(3);
}

// Result
// ↓
//lock ... (0.000975 sec.)
//await ... (0.001143 sec.)
//await ret = -15962300 (2.017199 sec.)

void awaitUninterruptibly ()

Causes the current thread to wait until it is signalled.

Please see also : await()

try (var executor = Executors.newSingleThreadExecutor()) {
    final var lock = new ReentrantLock();
    final var cond = lock.newCondition();

    final var future = executor.submit(() -> {
        System.out.println("lock ...");
        lock.lock();
        try {
            System.out.println("await ...");
            cond.awaitUninterruptibly();
            System.out.println("await OK!");
            System.out.println("isInterrupted : " + Thread.currentThread().isInterrupted());
        } finally {
            lock.unlock();
        }
    });

    TimeUnit.SECONDS.sleep(1);

    final var ret = future.cancel(true);
    System.out.println("cancel = " + ret);

    lock.lock();
    try {
        System.out.println("signal!");
        cond.signal();
    } finally {
        lock.unlock();
    }
}

// Result
// ↓
//lock ...
//await ...
//cancel = true
//signal!
//await OK!
//isInterrupted : true
try (var executor = Executors.newSingleThreadExecutor()) {
    final var lock = new ReentrantLock();
    final var cond = lock.newCondition();

    final var future = executor.submit(() -> {
        System.out.println("lock ...");
        lock.lock();
        try {
            System.out.println("await ...");
            cond.await();
            System.out.println("await OK!");
        } catch (InterruptedException e) {
            System.out.println("InterruptedException!");
        } finally {
            lock.unlock();
        }
    });

    TimeUnit.SECONDS.sleep(1);

    final var ret = future.cancel(true);
    System.out.println("cancel = " + ret);
}

// Result
// ↓
//lock ...
//await ...
//InterruptedException!
//cancel = true

boolean awaitUntil (Date deadline)

Causes the current thread to wait until it is signalled or interrupted, or the specified deadline elapses.

final long current = System.nanoTime();
final DoubleSupplier elapsedTime = () -> (System.nanoTime() - current) / 1000000000.0;

final var deadline = Instant.now().plusSeconds(2);

try (var executor = Executors.newSingleThreadExecutor()) {
    final var lock = new ReentrantLock();
    final var cond = lock.newCondition();

    executor.submit(() -> {
        System.out.printf("lock ... (%f sec.)%n", elapsedTime.getAsDouble());
        lock.lock();
        try {
            System.out.printf("await ... (%f sec.)%n", elapsedTime.getAsDouble());

            final var ret = cond.awaitUntil(Date.from(deadline));
            System.out.printf("await ret = %b (%f sec.)%n", ret, elapsedTime.getAsDouble());
        } catch (InterruptedException e) {
            System.out.println("InterruptedException!");
        } finally {
            lock.unlock();
        }
    });

    TimeUnit.SECONDS.sleep(1);

    lock.lock();
    try {
        System.out.printf("signal! (%f sec.)%n", elapsedTime.getAsDouble());
        cond.signal();
    } finally {
        lock.unlock();
    }
}

// Result
// ↓
//lock ... (0.003268 sec.)
//await ... (0.004692 sec.)
//signal! (1.007036 sec.)
//await ret = true (1.007370 sec.)

An example with timeout.

final long current = System.nanoTime();
final DoubleSupplier elapsedTime = () -> (System.nanoTime() - current) / 1000000000.0;

final var deadline = Instant.now().plusSeconds(2);

try (var executor = Executors.newSingleThreadExecutor()) {
    final var lock = new ReentrantLock();
    final var cond = lock.newCondition();

    executor.submit(() -> {
        System.out.printf("lock ... (%f sec.)%n", elapsedTime.getAsDouble());
        lock.lock();
        try {
            System.out.printf("await ... (%f sec.)%n", elapsedTime.getAsDouble());

            final var ret = cond.awaitUntil(Date.from(deadline));
            System.out.printf("await ret = %b (%f sec.)%n", ret, elapsedTime.getAsDouble());
        } catch (InterruptedException e) {
            System.out.println("InterruptedException!");
        } finally {
            lock.unlock();
        }
    });

    TimeUnit.SECONDS.sleep(3);
}

// Result
// ↓
//lock ... (0.000794 sec.)
//await ... (0.000954 sec.)
//await ret = false (2.012004 sec.)

void signal ()

Wakes up one waiting thread.

Please see await().

void signalAll ()

Wakes up all waiting threads.

final long current = System.nanoTime();
final DoubleSupplier elapsedTime = () -> (System.nanoTime() - current) / 1000000000.0;

try (var executor = Executors.newFixedThreadPool(3)) {
    final var lock = new ReentrantLock();
    final var cond = lock.newCondition();

    for (int i = 1; i <= 3; i++) {
        final var id = i;
        TimeUnit.MILLISECONDS.sleep(100);

        executor.submit(() -> {
            lock.lock();
            try {
                System.out.printf("%d : await ... (%f sec.)%n", id, elapsedTime.getAsDouble());
                cond.await();
                System.out.printf("%d : await OK! (%f sec.)%n", id, elapsedTime.getAsDouble());
            } catch (InterruptedException e) {
                System.out.println("InterruptedException!");
            } finally {
                lock.unlock();
            }
        });
    }

    TimeUnit.SECONDS.sleep(5);

    lock.lock();
    try {
        System.out.printf("signal all! (%f sec.)%n", elapsedTime.getAsDouble());
        cond.signalAll();
    } finally {
        lock.unlock();
    }
}

// Result
// ↓
//1 : await ... (0.105841 sec.)
//2 : await ... (0.213281 sec.)
//3 : await ... (0.321265 sec.)
//signal all! (5.330418 sec.)
//1 : await OK! (5.330721 sec.)
//2 : await OK! (5.330926 sec.)
//3 : await OK! (5.331123 sec.)

An example with the signal method.

final long current = System.nanoTime();
final DoubleSupplier elapsedTime = () -> (System.nanoTime() - current) / 1000000000.0;

try (var executor = Executors.newFixedThreadPool(3)) {
    final var lock = new ReentrantLock();
    final var cond = lock.newCondition();

    for (int i = 1; i <= 3; i++) {
        final var id = i;
        TimeUnit.MILLISECONDS.sleep(100);

        executor.submit(() -> {
            lock.lock();
            try {
                System.out.printf("%d : await ... (%f sec.)%n", id, elapsedTime.getAsDouble());
                cond.await();
                System.out.printf("%d : await OK! (%f sec.)%n", id, elapsedTime.getAsDouble());
            } catch (InterruptedException e) {
                System.out.println("InterruptedException!");
            } finally {
                lock.unlock();
            }
        });
    }

    TimeUnit.SECONDS.sleep(5);

    for (int i = 0; i < 3; i++) {
        lock.lock();
        try {
            System.out.printf("signal! (%f sec.)%n", elapsedTime.getAsDouble());
            cond.signal();
        } finally {
            lock.unlock();
        }

        TimeUnit.SECONDS.sleep(2);
    }
}

// Result
// ↓
//1 : await ... (0.105298 sec.)
//2 : await ... (0.214365 sec.)
//3 : await ... (0.324142 sec.)
//signal! (5.332321 sec.)
//1 : await OK! (5.332855 sec.)
//signal! (7.369622 sec.)
//2 : await OK! (7.369812 sec.)
//signal! (9.384503 sec.)
//3 : await OK! (9.384861 sec.)

Related posts

To top of page