솔직히 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"); } } } }
댓글 없음:
댓글 쓰기