Java : Exchanger with Examples

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


Summary

A synchronization point at which threads can pair and swap elements within pairs. Each thread presents some object on entry to the exchange method, matches with a partner thread, and receives its partner's object on return.

Class diagram

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

final var exchanger = new Exchanger<List<String>>();
try (final var executor = Executors.newFixedThreadPool(2)) {

    executor.submit(() -> {
        try {
            final var x = List.of("a", "b", "c");
            System.out.printf("A : task start : x = %s (%f sec.)%n", x, elapsedTime.getAsDouble());

            final var ret = exchanger.exchange(x);

            System.out.printf("A : exchange OK! : ret = %s (%f sec.)%n",
                    ret, elapsedTime.getAsDouble());

        } catch (InterruptedException e) {
            System.out.println("InterruptedException!");
        }
    });

    TimeUnit.SECONDS.sleep(2);

    executor.submit(() -> {
        try {
            final var x = List.of("X", "Y", "Z");
            System.out.printf("B : task start : x = %s (%f sec.)%n", x, elapsedTime.getAsDouble());

            final var ret = exchanger.exchange(x);

            System.out.printf("B : exchange OK! : ret = %s (%f sec.)%n",
                    ret, elapsedTime.getAsDouble());

        } catch (InterruptedException e) {
            System.out.println("InterruptedException!");
        }
    });
}

// Result
// ↓
//A : task start : x = [a, b, c] (0.002765 sec.)
//B : task start : x = [X, Y, Z] (2.019055 sec.)
//B : exchange OK! : ret = [a, b, c] (2.019486 sec.)
//A : exchange OK! : ret = [X, Y, Z] (2.019660 sec.)

Constructors

Exchanger ()

Creates a new Exchanger.

Please see exchange(V x).

Methods

V exchange (V x)

Waits for another thread to arrive at this exchange point (unless the current thread is interrupted), and then transfers the given object to it, receiving its object in return.

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

final var exchanger = new Exchanger<List<String>>();
try (final var executor = Executors.newFixedThreadPool(2)) {

    executor.submit(() -> {
        try {
            final var x = List.of("a", "b", "c");
            System.out.printf("A : task start : x = %s (%f sec.)%n", x, elapsedTime.getAsDouble());

            final var ret = exchanger.exchange(x);

            System.out.printf("A : exchange OK! : ret = %s (%f sec.)%n",
                    ret, elapsedTime.getAsDouble());

        } catch (InterruptedException e) {
            System.out.println("InterruptedException!");
        }
    });

    TimeUnit.SECONDS.sleep(2);

    executor.submit(() -> {
        try {
            final var x = List.of("X", "Y", "Z");
            System.out.printf("B : task start : x = %s (%f sec.)%n", x, elapsedTime.getAsDouble());

            final var ret = exchanger.exchange(x);

            System.out.printf("B : exchange OK! : ret = %s (%f sec.)%n",
                    ret, elapsedTime.getAsDouble());

        } catch (InterruptedException e) {
            System.out.println("InterruptedException!");
        }
    });
}

// Result
// ↓
//A : task start : x = [a, b, c] (0.002765 sec.)
//B : task start : x = [X, Y, Z] (2.019055 sec.)
//B : exchange OK! : ret = [a, b, c] (2.019486 sec.)
//A : exchange OK! : ret = [X, Y, Z] (2.019660 sec.)
final var exchanger = new Exchanger<List<String>>();
try (final var executor = Executors.newFixedThreadPool(2)) {

    final var future = executor.submit(() -> {
        try {
            final var x = List.of("a", "b", "c");
            System.out.println("A : task start : x = " + x);

            final var ret = exchanger.exchange(x);
            System.out.println("A : exchange OK! : ret = " + ret);

        } catch (InterruptedException e) {
            System.out.println("InterruptedException!");
        }
    });

    TimeUnit.SECONDS.sleep(2);

    System.out.println("future : cancel!");

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

// Result
// ↓
//A : task start : x = [a, b, c]
//future : cancel!
//InterruptedException!
//cancelled = true

V exchange (V x, long timeout, TimeUnit unit)

Waits for another thread to arrive at this exchange point (unless the current thread is interrupted or the specified waiting time elapses), and then transfers the given object to it, receiving its object in return.

Please see also : exchange(V x)

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

final var exchanger = new Exchanger<List<String>>();
try (final var executor = Executors.newFixedThreadPool(2)) {

    executor.submit(() -> {
        try {
            final var x = List.of("a", "b", "c");
            System.out.printf("A : task start : x = %s (%f sec.)%n", x, elapsedTime.getAsDouble());

            final var ret = exchanger.exchange(x, 5, TimeUnit.SECONDS);

            System.out.printf("A : exchange OK! : ret = %s (%f sec.)%n",
                    ret, elapsedTime.getAsDouble());

        } catch (InterruptedException | TimeoutException e) {
            System.out.printf("A : %s (%f sec.)%n",
                    e.getClass().getSimpleName(), elapsedTime.getAsDouble());
        }
    });
}

// Result
// ↓
//A : task start : x = [a, b, c] (0.002542 sec.)
//A : TimeoutException (5.018461 sec.)

Related posts

To top of page