天天看點

Java栅欄——Exchanger

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();
				}
			}
		}
	}
}