Используйте CyclicBarrier
.Вот пример релевантности из его Javadoc:
Средство синхронизации, которое позволяет всем потокам ожидать друг друга, чтобы достичь общей барьерной точки.CyclicBarriers полезны в программах, включающих группу потоков фиксированного размера, которые иногда должны ждать друг друга.Барьер называется циклическим, поскольку его можно использовать повторно после освобождения ожидающих потоков.
Итак, вам нужно создать CyclicBarrier
для ряда 2
сторон и позволить потоку-получателю вызывать await()
после ACK и позволить потоку-отправителю вызывать await()
перед выполнениемОТПРАВИТЬ.
Вот SSCCE , с которого можно начать.
package com.stackoverflow.q3379797;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Test {
public static void main(String[] args) {
CyclicBarrier barrier = new CyclicBarrier(2);
Receiver receiver = new Receiver(barrier);
Sender sender = new Sender(barrier);
ExecutorService executor = Executors.newFixedThreadPool(2);
executor.submit(receiver);
executor.submit(sender);
}
}
class Receiver implements Runnable {
private CyclicBarrier barrier;
public Receiver(CyclicBarrier barrier) {
this.barrier = barrier;
}
@Override
public void run() {
while (true) {
try {
// Wait for ACK (the sleep just simulates that).
Thread.sleep(2000);
System.out.println("ACK");
// Then notify.
barrier.await();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
class Sender implements Runnable {
private CyclicBarrier barrier;
public Sender(CyclicBarrier barrier) {
this.barrier = barrier;
}
@Override
public void run() {
while (true) {
try {
// Wait for notify.
barrier.await();
// Now do SEND.
System.out.println("SEND");
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
В выводе вы увидите следующее:
(2 seconds)
ACK
SEND
(2 seconds)
ACK
SEND
(2 seconds)
ACK
SEND