package xyz.biandeshen.thread;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Deque;
import java.util.concurrent.Exchanger;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;
/**
* @author fjp
* @Title: TestExchager
* @ProjectName commons-tests
* @Description: Two-Party Barrier ==== Exchanger 兩方交換栅欄(代碼中休眠為格式需要,實際無需休眠)
* @date 2019/11/129:18
*/
@SuppressWarnings("all")
public class TestExchager {
public static void main(String[] args) {
Exchanger<Deque<String>> exchanger = new Exchanger<>();
new Thread(new Producer(exchanger)).start();
new Thread(new Consumer(exchanger)).start();
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
static class Producer implements Runnable {
private static final Logger logger = LoggerFactory.getLogger(Producer.class);
private static Exchanger<Deque<String>> dequeExchanger;
private static Deque<String> stringDeque = new LinkedBlockingDeque<>();
public Producer(Exchanger<Deque<String>> dequeExchanger) {
this.dequeExchanger = dequeExchanger;
}
@Override
public void run() {
Thread.currentThread().setName("Producer-");
for (int i = 0; i < 5; i++) {
try {
stringDeque.addFirst(String.valueOf(i));
logger.info(Thread.currentThread().getName() + "交換前size: = " + stringDeque.size());
// 通過程式休眠來确定代碼執行順序
// 由于exchanger 會阻塞,直到另一個結果産生,才會執行交換,是以可在此處使用休眠
stringDeque = dequeExchanger.exchange(stringDeque);
TimeUnit.MILLISECONDS.sleep(10);
logger.info(Thread.currentThread().getName() + "交換後size: = " + stringDeque.size());
System.out.println();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
static class Consumer implements Runnable {
private static final Logger logger = LoggerFactory.getLogger(Consumer.class);
private static Exchanger<Deque<String>> dequeExchanger;
private static Deque<String> stringDeque = new LinkedBlockingDeque<>();
public Consumer(Exchanger<Deque<String>> dequeExchanger) {
this.dequeExchanger = dequeExchanger;
}
@Override
public void run() {
Thread.currentThread().setName("Consumer-");
for (int i = 0; i < 5; i++) {
try {
TimeUnit.MILLISECONDS.sleep(2);
logger.info(Thread.currentThread().getName() + "交換前size: = " + stringDeque.size());
stringDeque = dequeExchanger.exchange(stringDeque);
logger.info(Thread.currentThread().getName() + "交換後size: = " + stringDeque.size());
logger.info(Thread.currentThread().getName() + "stringDeque.getFirst() = " + stringDeque.peekFirst());
TimeUnit.MILLISECONDS.sleep(8);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}