동시성제어(Thread)

동시성제어(Thread)

실행코드

package study.thread;

import java.util.UUID;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;


/**
 * 생산자-소비자 문제에 대한 극히 간단한 예제
 *
 * BlockingQueue를 사용했기 때문에 동기화 이슈가 없음.
 * 한순간에 하나의 Thread만 queue에 put 또는 take(get)을 할 수 있음.
 *
 */
public class ThreadExample {

	public static final BlockingQueue<Product> QUEUE = new LinkedBlockingQueue<>();


	public static void main( String[] args ) {
		Thread supplier = new Thread( new Supplier( ThreadExample.QUEUE ) );
		Thread consumer1 = new Thread( new Consumer( ThreadExample.QUEUE, "소비자1" ) );
		Thread consumer2 = new Thread( new Consumer( ThreadExample.QUEUE, "소비자2" ) );

		supplier.start();
		consumer1.start();
		consumer2.start();
	}

}



/**
 * 생산/소비가 이루어지는 제품
 */
class Product {

	private String id;


	public Product() {
		this.id = UUID.randomUUID().toString();
	}


	public String getId() {
		return this.id;
	}

}



/**
 * 생산자
 */
class Supplier implements Runnable {

	private final BlockingQueue<Product> queue;


	public Supplier( BlockingQueue<Product> queue ) {
		this.queue = queue;
	}


	@Override
	public void run() {
		int count = 0;
		while( true ) {
			if( this.queue.size() < 1000 ) {
				synchronized( this.queue ) {
					for( int i = 0 ; i < 3 ; i++ ) {
						this.queue.add( new Product() );
					}
				}
			}
			try {
				if( count++ % 100 == 0 ) {
					count = 0; // Overflow방지
					Thread.sleep( 100L );
				}
			} catch( InterruptedException e ) {
				e.printStackTrace();
				break;
			}
		}
	}

}



/**
 * 소비자
 */
class Consumer implements Runnable {

	private final BlockingQueue<Product> queue;

	private final String name;


	public Consumer( BlockingQueue<Product> queue, String consumerName ) {
		this.queue = queue;
		this.name = consumerName;
	}


	@Override
	public void run() {
		while( true ) {
			try {
				System.out.println( this.name + " : " + this.queue.take().getId() + " / " + this.queue.size() );
				Thread.sleep( 200L );
			} catch( InterruptedException e ) {
				e.printStackTrace();
			}
		}
	}
}

실행결과

소비자1 : bdf16be9-0147-4581-88b0-995cd6b7a476 / 1
소비자2 : b8760c0f-8ecb-445f-98f5-328532e46f39 / 2
소비자2 : 14659b8f-f4cd-4549-b5b7-78ca89c33697 / 3
소비자1 : 0f1e8a89-27a5-432f-ab36-198e01ab7437 / 2
소비자1 : 81ed1ef2-67ef-4713-9c5a-cd11bc75d667 / 7
소비자2 : 2c69b172-c0ca-4ed6-8d5c-c1af76cfb564 / 6
소비자1 : 94bf405d-e2b0-4181-836d-f473e7bf02e4 / 11
소비자2 : 3ebf8935-b4ad-4cc4-8d4c-a80d2204bd39 / 10
소비자2 : 4c9be5b1-d27a-40ab-a49c-cf064c919064 / 15
소비자1 : 2f680001-0e22-4243-8ea6-db0a6b4febf6 / 14
소비자2 : 64f0a6b3-7ca2-4c3f-b129-ef8684281b0f / 19
소비자1 : baff0692-fb5f-4082-8f3a-1b36a8d7e531 / 18
소비자2 : e6b769f1-3714-4aaf-acea-017ca11f9a88 / 23
소비자1 : f236e5a0-a443-4e23-a7c8-941c59699e0d / 22
소비자2 : 9d5e52cf-2e33-4c21-8a4d-abcd23143014 / 26
소비자1 : 5ecb7706-b951-4665-b814-a10950021e70 / 26
소비자1 : 6c60011f-a730-4928-b861-8831fc5e8643 / 31
소비자2 : 08b2029a-b2ac-49f2-8e6b-a57704401d3a / 30
소비자2 : f0fd5e15-80e1-4149-a542-5cb5851defdc / 34
소비자1 : bee2c10d-f94c-4f56-9072-9ba1c6242a14 / 35
소비자2 : f356186b-681a-4e6a-aac4-a6ee3dfff436 / 39
소비자1 : 173db577-f737-4213-bb41-1183dfc5472b / 38
소비자2 : 3aa57358-0d1a-4d8c-8d87-b7052948f8b9 / 43
소비자1 : b6dd4a8c-8390-4a92-abeb-0de175956ce0 / 42
소비자2 : c50dca21-eb65-4d3b-bfe8-209dd6641830 / 47
소비자1 : 7302828f-1a53-4062-b8dd-10e05215d311 / 46

이하 생략...

Written with StackEdit.