
블랙잭 미션을 진행하면서 자주 사용하는 인스턴스가 많이 보였다.
4가지 모양과 13가지 수로 만들 수 있는 카드는 총 52장이다.
즉, 블랙잭 게임에서 52장의 카드만 사용하고, 미리 생성해서 필요할 때마다 사용하면 성능에 이점이 있다.
미리 생성해서 필요할 때마다 사용하는 캐싱과 풀에 대해서 알아보자!
처음 요청 시 데이터를 생성하거나 검색하고, 이후 같은 요청이 들어오면 저장된 데이터를 반환하여 성능을 향상시킨다.
캐시는 일정 시간이 지나거나 데이터가 변경될 때 업데이트되거나 제거된다.
사용 예: 웹 페이지 캐싱, 데이터베이스 쿼리 결과 캐싱, 이미지 캐싱 등
애플리케이션이 시작할 때 미리 정의된 수의 리소스를 생성하고, 리소스 풀에 보관한다.
사용이 필요할 때 풀에서 리소스를 할당받고, 사용이 끝나면 리소스를 풀에 반환합니다. 이 과정을 통해 리소스의 생성 및 파괴로 인한 오버헤드를 줄입니다.
사용 예: 데이터베이스 연결 풀, 스레드 풀, 객체 풀 등
아래는 내가 블랙잭 미션에서 적용한 POOL의 코드이다.
public class Card {
private static final Map<String, Card> CARD_POOL = new HashMap<>();
private final CardRank cardRank;
private final CardShape cardShape;
static {
for (CardRank cardRank : CardRank.values()) {
for (CardShape cardShape : CardShape.values()) {
CARD_POOL.put(toKey(cardRank, cardShape), new Card(cardRank, cardShape));
}
}
}
private Card(CardRank cardRank, CardShape cardShape) {
this.cardRank = cardRank;
this.cardShape = cardShape;
}
public static Card of(CardRank cardRank, CardShape cardShape) {
return CARD_POOL.get(toKey(cardRank, cardShape));
}
private static String toKey(CardRank cardRank, CardShape cardShape) {
return cardRank.getRank() + cardShape.getShape();
}
// 생략 ...
}
우선 CARD_POOL을 Map으로 만들고 정적 초기화 블록을 이용해서 카드들을 초기화할 수 있다.
getRank와 getShape을 합친 이름으로 toKey를 만들어서 Map의 Key로 사용했다.
이후에 카드를 가져오고 싶으면 static Card of 메서드를 통해 CARD_POOL의 카드를 가져올 수 있다.
ConcurrentHashMap을 사용해서 멀티스레드 환경에 대응할 수도 있다.
정적 초기화 블록은
static {}이 부분이다.
자주 사용하는 값들을 캐싱해서 성능을 향상시키자!