관리 메뉴

nalaolla

디자인패턴#5 생산자/소비자 패턴( Producer/Consumer Pattern) 본문

JAVA/999. 디자인패턴

디자인패턴#5 생산자/소비자 패턴( Producer/Consumer Pattern)

날아올라↗↗ 2020. 11. 23. 17:32
728x90

[개요]
아래의 코드는 Linear( 선형큐)가 아닌 Circle Queue( 순환큐)를 이용하여 생산자/소비자 패턴을 구현해 보았습니다.

생산자/소비자 패턴은 멀티쓰레드 환경에서 주로 쓰이는 패턴입니다. 생산자와 소비자는 하나의 클래스를 공유하고 그 클래스는 큐구조를 가지게 됩니다.

생산자는 데이터를 지속적으로 만들어 큐에 넣을 것이고 소비자는 데이터를 지속적으로 큐에서 빼낼 것입니다.

[구조]

[Main.java]
package provider_consumer;

public class Main {
public static void main(String[] args) {

    int size = 100;
    Table table = new Table(100);

    Thread provider = new Thread(new Provider(table));
    Thread consumer = new Thread(new Consumer(table));

    provider.start();
    consumer.start();
}

}
[Table.java]
package provider_consumer;

public class Table {

private int[] queue;
private int capacity;
private int head;
private int tail;
private int count;

public Table(int capacity) {
    this.capacity = capacity;
    queue = new int[ capacity];
}

/**
 * 큐에서 값을 하나 빼내는 메소드
 * @return
 * @throws InterruptedException 
 */
public synchronized int pop() throws InterruptedException {

    while( count <= 0) {
        wait();
    }

     int retValue = queue[ tail];
     tail =  ( tail + 1) % queue.length;
     count--;
     notifyAll();

    return retValue;
}

/**
 * 큐에 값을 삽입하는 메소드
 * @param ranNum
 * @throws InterruptedException
 */
public synchronized void push(int ranNum) throws InterruptedException {

    while( count >= queue.length) {
        wait();
    }

    queue[ head] = ranNum;
    head = ( head + 1) % queue.length;
    count++;
    notifyAll();

}

}
[Provier.java]
package provider_consumer;

public class Provider implements Runnable {

private Table table;

public Provider(Table table) {
    this.table = table;
}

@Override
public void run() {

    while( true) {
        try {
            int ranNum = ( int )(Math.random() * 100) + 1;
            System.out.printf("입력 : %s \n", ranNum);
            table.push( ranNum);
            Thread.sleep(((int)(Math.random() * 500) + 1));
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}

}
[Consumer.java]
package provider_consumer;

public class Consumer implements Runnable {

private Table table;

public Consumer(Table table) {
    this.table = table;
}

@Override
public void run() {
    while( true) {
        try {
            int num = table.pop();
            System.out.printf("출력 : %d \n", num);
            Thread.sleep( ((int)(Math.random() * 500) + 1));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

}

728x90