우아한 프로그래밍
article thumbnail

[개요]

아래의 코드는 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();
            }
        }

    }

}
profile

우아한 프로그래밍

@자바조아!

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!