[자바 디자인 패턴] 생성패턴 - 오브젝트풀 패턴

2021. 3. 17. 16:42 JAVA/Design Patterns

생성패턴 목록

 

스레드 풀과 같이 한정된 리소스에서 자원을 재사용하는 방식을 적용하기를 원할 때 사용하면 성능개선에 좋을 것 같다.

 

장점

- 응용프로그램의 성능을 크게 향상시킵니다.

- 클래스 인스턴스 초기화 속도가 높은 상황에서 가장 효과적입니다.

- 커넥션을 관리하고 이를 재사용하고 공유할 수 있는 방법을 제공합니다.

- 만들 수 있는 최대 객체 수에 대한 제한을 제공할 수 있습니다.

 

사용시기

- 어플리케이션에서 사용하기에 비용이 높은 객체가 필요한 경우 (데이터베이스 커넥션)

- 서로 다른 시간에 동일한 리소스를 필요로 하는 여러 클라이언트가 있는 경우

 

UML

 

ObjectPool Class : ObjectPool

public abstract class ObjectPool<T>{
    private ConcurrentLinkedQueue<T> pool;
    private ScheduledExecutorService executorService;
    
    public ObjectPool(final int minObjects){
        initialize(minObjects);
    }
    
    public ObjectPool(final int minObjects, final int maxObjects, final long validationInterval){
        initialize(minObjects);
        
        executorService = Executors.newSingleThreadScheduledExecutor();
        executorService.scheduleWithFixedDelay(new Runnable(){
            @Override
            public void run(){
                int size = pool.size();
                
                if(size < minObjects){
                    int sizeToBeAdded = minObjects + size;
                    for(int i=0; i<sizeToBeAdded; i++){
                        pool.add(createObject());
                    }
                }
                else if(size > maxObjects){
                    int sizeToBeRemoved = size - maxObjects;
                    for(int i=0; i<sizeToBeRemoved; i++){
                        pool.poll();
                    }
                }
            }
        }, validationInterval, validationInterval, TimeUnit.SECONDS);
    }
    
    public T borrowObject(){
        T object;
        if((object = pool.poll()) == null){
            object = createObject();
        }
        return object;
    }
    
    public void returnObject(T object){
        if(object == null){
            return;
        }
        this.pool.offer(object);
    }
    
    public void shutdown(){
        if(executorService != null){
            executorService.shutdown();
        }
    }
    
    protected abstract T createObject();
    
    private void initialize(final int minObjects){
        pool = new ConcurrentLinkedQueue<T>();
        for(int i=0; i<minObjects; i++){
            pool.add(creatObject());
        }
    }
}

 

Process Class : ExportingProcess, ExportingTask

public class ExportingProcess{
    private long processNo;
    
    public ExportingProcess(long processNo){
        this.processNo = processNo;
        System.out.println("Object with process no. " + processNo + " was created");
    }
    
    public long getProcessNo(){
        return processNo;
    }
}
public class ExportingTask implements Runnable{
    private ObjectPool<ExportingProcess> pool;
    private int threadNo;
    
    public ExportingTask(ObjectPool<ExportingProcess> pool, int threadNo){
        this.pool = pool;
        this.threadNo = threadNo;
    }
    
    public void run(){
        ExportingProcess exportingProcess = pool.borrowObject();
        System.out.println("Thread " + threadNo + ": Object with process no. " 
            + exportingProcess.getProcessNo() + " was borrowed");
        
        pool.returnObject(exportingProcess);
        System.out.println("Thread " + threadNo +": Object with process no. "
            + exportingProcess.getProcessNo() + " was returned");
    }
}

 

Operation Class : ObjectPoolDemo

public class ObjectPoolDemo{
    private ObjectPool<ExportingProcess> pool;
    private AtomicLong processNo=new AtomicLong(0);
    
    public void setUp(){
        pool = new ObjectPool<ExportingProcess>(4, 10, 5){
            @Override
            protected ExportingProcess createObject(){
                return new ExportingProcess(processNo.incrementAndGet());
            }
        }
    }
    
    public void tearDown(){
        pool.shutdown();
    }
    
    public void testObjectPool(){
        ExecutorService executor = Executors.newFixedThreadPool(8);
        
        executor.execute(new ExportingTask(pool, 1));
        executor.execute(new ExportingTask(pool, 2));
        executor.execute(new ExportingTask(pool, 3));
        executor.execute(new ExportingTask(pool, 4));
        executor.execute(new ExportingTask(pool, 5));
        executor.execute(new ExportingTask(pool, 6));
        executor.execute(new ExportingTask(pool, 7));
        executor.execute(new ExportingTask(pool, 8));
        
        executor.shutdown();
        try{
            executor.awaitTermination(30, TimeUnit.SECONDS);
        }catch(InterruptedException e){
            e.printStackTrace();
        }
    }
    
    public static void main(String[] args){
        ObjectPoolDemo op = new ObjectPoolDemo();
        op.setUp();
        op.tearDown();
        op.testObjectPool();
    }
}

 

 

출처 : https://www.javatpoint.com/

know-one-by-one.tistory.com/37