티스토리 뷰
Exchanger 는 뜻 그대로 쓰레드상에서 두 개의 인스턴스를 교환해주는 역할을 한다. 만약 한쪽의 쓰레드에서만 교환 메소드를 호출한다면 다른쪽에서 교환 메소드를 호출하기 전까지 대기하고 있는데.
이 클래스는 java 의 gc 와 같은 동작에서 사용할 수 있다.
예를 들어 설명하면 다음과 같다. (이해를 돕기 위하여 '요청' 이라는 표현을 사용하였다. 정확히는 교환 대상이 되는 인스턴스 값을 인자로 하는 교환 메소드 호출이다.)
1. 데이터를 '스택에 쌓는 쓰레드' 와, '스택을 비우는 쓰레드' 가 있다. 이 두 개의 쓰레드에는 각각의 '스택' 이 있다.
2. 데이터를 '스택에 쌓는 쓰레드' 는 계속해서 데이터를 자신의 '스택' 에 추가한다. 이 동작을 반복하다 스택이 가득차면 '스택' 교환을 요청하고 3번 과정이 끝날 때 까지 모든 동작을 대기한다. 즉, 다른쪽에서도 교환 요청이 일어날 때까지 대기하는 것이다.
3. '스택을 비우는 쓰레드' 에서 스택을 모두 비운다. 스택을 모두 비우면 가득찬 스택을 가져오기 위하여 데이터를 '스택에 쌓는 쓰레드' 의 '스택'과 교환 요청을 한다.
4. 한 쌍의 '스택' 에 대하여 교환 요청이 이루어졌으므로 '스택에 쌓는 쓰레드' 의 가득찬 '스택'은 '스택을 비우는 쓰레드' 로 이동하여 가득찬 '스택'을 비울 수 있도록 한다. 또, '스택을 비우는 쓰레드' 의 비어있는 '스택'은 '스택에 쌓는 쓰레드' 로 이동하여 비어있는 '스택' 에 데이터를 다시 쌓을 수 있도록 한다. 그리고 1번 과정을 반복한다.
이를 예제코드로 표현하면 아래와 같다.
예제코드:
/** * 스택의 최대 크기. */ public final static int STACK_CAPACITY = 8; private Exchanger<LinkedList<Integer>> mExchanger = new Exchanger<LinkedList<Integer>>(); class PushLoop implements Runnable { /** int 값을 넣는데 사용하는 스택. */ LinkedList<Integer> integerStack = new LinkedList<Integer>(); /** 키 입력을 받는다. */ private Scanner keyScanner = new Scanner(System.in); public void run() { while(!Thread.interrupted()) { try { // 스택의 최대 크기를 넘기지 않는 범위내에서 입력받은 값들을 스택에 넣는다. while(integerStack.size() < STACK_CAPACITY) { int value = keyScanner.nextInt(); integerStack.addLast(value); } // 스택이 가득차면 메세지를 출력하고, 비어있는 스택(integerStack)과 교환한다. // 만약 교환될(비어있는) 스택이 없다면 대기한다. System.out.println("PushLoop : Full Stack."); integerStack = mExchanger.exchange(integerStack); } catch (InterruptedException e) { e.printStackTrace(); } } } } class EmptyLoop implements Runnable { /** * 값을 비우는 스택. */ LinkedList<Integer> integerStack = new LinkedList<Integer>(); public void run() { while(!Thread.interrupted()) { try { // 스택내에 값이 비어있지 않으면 계속 비운다. while(!integerStack.isEmpty()) { int value = integerStack.removeLast(); System.out.println(value); } // 스택이 비어지면 메세지를 출력하고, 가득찬 스택(integerStack)과 교환한다. // 만약 교환될(가득찬) 스택이 없다면 대기한다. System.out.println("EmptyLoop : Empty Stack."); integerStack = mExchanger.exchange(integerStack); } catch (InterruptedException e) { e.printStackTrace(); } } } } public void runThread() { new Thread(new PushLoop()).start(); new Thread(new EmptyLoop()).start(); }
위 예제 코드에서 runThread() 를 호출하면 값을 입력 받아서 stack 에 쌓는 쓰레드와 동시에 비우는 쓰레드가 작동한다. 결과는 다음과 같다.
실행 결과(초록색 폰트가 입력된 값이다.):
EmptyLoop : Empty Stack. 100 200 300 400 500 600 700 800 PushLoop : Full Stack. 800 700 600 500 400 300 200 100 EmptyLoop : Empty Stack.
'개발 관련 > Java' 카테고리의 다른 글
JAVA 텍스트 파일의 Encoding 정보 가져오기 + String Encoding 변환하기. (1) | 2015.11.18 |
---|---|
Guava 사용 요약 슬라이드. (0) | 2015.04.17 |
[JAVA:병렬 프로그래밍 - 2] CyclicBarrier 사용하기. (0) | 2014.09.02 |
[JAVA:병렬 프로그래밍 - 1] CountDownLatch 사용하기. (0) | 2014.08.19 |
[JAVA] int 또는 float 를 byte 배열 타입으로 변환. byte 배열을 int 또는 float 으로 변환, Unsigned 표현. (1) | 2014.03.04 |
- Total
- Today
- Yesterday
- 안드로이드 개발
- activity
- WS2812B
- 스마트 무드등
- 블루투스
- ESP8266
- 개발
- 아두이노
- noidemcu
- oled
- arduino
- ATtiny85
- 침블락
- json
- 가습기
- 이더넷
- 알리익스프레스
- NeoPixel
- 안드로이드
- ENC28J60
- Java
- 병렬 프로그래밍
- ndk
- bluetooth
- Cheapduino
- 칩두이노
- Android
- 부트로더
- HC-06
- Iot
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 27 | 28 | 29 | 30 |