Dalej pozostajemy w tematach związanych z pakietem java.util.concurrent. Dzisiejszy synchronizator pracy to Exchanger. Jak nazwa sugeruje służy on do wymiany danych pomiędzy dwoma wątkami. Podczas tworzenia tego synchronizatora określamy jakiego typu dane chcemy wymienić. Dane zostaną wymienione dopiero, gdy dwa wątki będą gotowe.

Problem

W naszej aplikacji chcielibyśmy wymieniać dane w sposób asynchroniczny pomiędzy dwoma wątkami. Kolejnym założeniem jest to, iż oba wątki wymienią się danymi dopiero po zakończeniu swojej asynchronicznej pracy.

Exchanger

Rozwiązaniem tego problemu jest klasa Exchanger, która pochodzi z pakietu java.util.concurrent. Pozwala wymieniać ona dane pomiędzy wątkami:

Zaczynamy od stworzenia klasy Exchanger, która jest parametryzowana typem:

1
Exchanger<String> stringExchanger = new Exchanger<>();

Po utworzeniu klasy do wymiany możemy stworzyć dwa zadania, które po wykonaniu pracy wymienią się danymi:

1
stringExchanger.exchange("First Value");

Napiszmy teraz test sprawdzający poprawność klasy Exchanger:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Test
void shouldExchangeValuesBetweenThreads() throws InterruptedException {
// Given
Exchanger<String> exchanger = new Exchanger<>();

Job firstJob = new Job(exchanger, "first");
Job secondJob = new Job(exchanger, "second");

// When
firstJob.start();
secondJob.start();

firstJob.join();
secondJob.join();

// Then
assertThat(firstJob.getExchangedValue()).isEqualTo("second");
assertThat(secondJob.getExchangedValue()).isEqualTo("first");
}

Implementacja wygląda następująco:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Job extends Thread {

private final Exchanger<String> exchanger;

private final String value;

private String exchangedValue;

Job(Exchanger<String> exchanger, String value) {
this.exchanger = exchanger;
this.value = value;
}

@Override
public void run() {
try {
exchangedValue = exchanger.exchange(value);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

String getExchangedValue() {
return exchangedValue;
}
}

GitHub

Całość jak zawsze na Githubie.