2012년 9월 13일 목요일

Pool 예제

솔직히 Pool 에 대해 제가 정확히 이해했는지 자신 없습니다. 아래 내용은 제 사견입니다.

Pool 은 미리 사용하려는 양 만큼의 버퍼를 할당해 놓고 객체를 사용하고 사용한 객체는 다시 버퍼에 넣고 재활용하는 방식의 방법입니다.

이런 방식의 장점으로는 버퍼를 재활용함으로 인해 객체 할당 및 제거에 드는 시간을 없앨 수 있다는 점이 있겠습니다.

Pool.java
 - queue 가 두개 필요합니다. 유휴 버퍼와 사용 가능 버퍼로 나눕니다.
 - 유휴 버퍼는 미리 빈 객체들로 원하는 갯수 만큼 채워 넣습니다.
 - 사용 가능 버퍼에는 유휴 버퍼에서 얻은 사용 객체로 하나씩 채워지게 됩니다.
 - 사용 가능 버퍼를 다 사용하고 나면 다시 유휴 버퍼로 옮겨 넣음으로써 나중에 다시 사용 가능하게 됩니다.

소스 코드 :
package pool.test;

import java.util.concurrent.LinkedBlockingQueue;

/**
 *
 * @param <T>
 */
public class Pool<T> {
    
    private LinkedBlockingQueue<T> free = new LinkedBlockingQueue<T>();
    private LinkedBlockingQueue<T> work = new LinkedBlockingQueue<T>();
    
    /**
     * 
     * @param creator
     * @param count
     */
    public Pool(PoolObjectCreator<T> creator, int count) {
        for (int i = 0;i < count; i++) {
            free.add(creator.create());
        }
    }
    
    /**
     * 
     * @return
     */
    public final T acquire() {
        return free.size() > 0 ? free.remove() : null;
    }
    
    /**
     * 
     * @param item
     */
    public final void enqueue(T item) {
        work.add(item);
    }
    
    /**
     * 
     * @return
     */
    public final T dequeue() {
        return work.size() > 0 ? work.remove() : null;
    }
    
    /**
     * 
     * @param item
     */
    public final void release(T item) {
        free.add(item);
    }
    
    /**
     *
     * @param <T>
     */
    public static interface PoolObjectCreator<T> {
        public T create();
    }
}

아래 내용은 Pool 사용 예제 입니다.
 - Producer 스레드에서는 1초 마다 pool 에 데이터를 넣습니다.
 - Consumer 스레드에서는 pool 에서 데이터를 받아서 화면에 값을 출력합니다.

Main.java :
package pool.test;

import java.io.BufferedReader;
import java.io.InputStreamReader;

/**
 *
 */
public class Main {
    
    private Consumer consumer;
    private Producer producer;
    
    /**
     * 
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
        
        Main main = new Main();
        main.start();
        
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        reader.readLine();
        
        main.stop();
        
        System.out.println("Done");
    }
    
    /**
     * 
     */
    public void start() {
        
        Pool<Container> pool = new Pool<Container>(new Pool.PoolObjectCreator<Container>() {
            @Override
            public Container create() {
                return new Container();
            }
        } , 10);
        
        
        producer = new Producer(pool);
        consumer = new Consumer(pool);
        
        producer.start();
        consumer.start();
    }
    
    /**
     * 
     */
    public void stop() {
        
        producer.interrupt();
        consumer.interrupt();
        
    }
    
    /**
     * 
     */
    public class Container {
        public int x;
    }
    
    
    
    /**
     *
     */
    public class Producer extends Thread {
        
        private Pool<Container> pool;
        
        public Producer(Pool<Container> pool) {
            this.pool = pool;
        }

        @Override
        public void run() {
            super.run();
            
            try {
                
                System.out.println("Producer :: start");
                
                int count = 0;
                
                Container container = null;
                while (!Thread.interrupted()) {
                    
                    if ((container = pool.acquire()) != null) {
                        
                        container.x = count++;
                        
                        pool.enqueue(container);
                        
                        Thread.sleep(1000);
                        
                    } else {
                        Thread.sleep(10);
                    }
                }
                
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                System.out.println("Producer :: done");
            }
        }
    }
    
    
    /**
     *
     */
    public class Consumer extends Thread {
        
        private Pool<Container> pool;
        
        public Consumer(Pool<Container> pool) {
            this.pool = pool;
        }

        @Override
        public void run() {
            super.run();
            
            try {
                
                System.out.println("Consumer :: start");
                
                Container container = null;
                while (!Thread.interrupted()) {
                    
                    if ((container = pool.dequeue()) != null) {
                        
                        System.out.printf("x : %d\n", container.x);
                        
                        pool.release(container);
                        
                    } else {
                        Thread.sleep(10);
                    }
                }
                
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                System.out.println("Consumer :: done");
            }
        }
    }
    
}


댓글 없음:

댓글 쓰기