본문 바로가기
Java

[Java] Stack vs Deque

by jn4624 2022. 7. 25.
반응형

공식 문서는 이렇게 말하고 있다.

 

더욱 완전하고 일관된 LIFO Stack 작업은 Deque 인터페이스 및 해당 구현을 사용하여 구현하는 것이다.

 

즉, Stack 대신 Deque의 구현체인 ArrayDeque 사용을 제안하고 있다.

 

Java에서 Vector는 특정 상황에서 효율적이지 않기 때문에 Thread Safe 않다고 할 수 있다. 그렇기 때문에 Vector를 상속 받은 Stack은 다음과 같은 단점이 존재한다.

 

  • 초기 용량 설정을 지원하지 않는다.
  • 모든 작업에 Lock이 사용된다.
  • 단일 스레드 실행 성능이 저하될 수 있다.
  • 단순한 Iterator의 탐색 작업에서도 get() 메서드 실행시 매번 Lock이 발생하게 되므로 오버헤드가 커진다.
  • Stack은 Vector를 상속 받았기 때문에 다중 상속을 지원하지 않는다.

 

Deque 인터페이스를 사용하면 필요한 모든 Stack 작업을 제공하기 때문에 편리하다. 또한, 작업에 Lock을 사용하지 않기 때문에 단일스레드에서도 문제가 발생하지 않는다.

 

다만, 다중스레드 실행의 경우 문제가 될 수 있지만 ArrayDeque에 대한 동기화 데코레이터를 구현할 수 있다. 데코레이터는 메소드가 실행되기 전에 먼저 실행되는 메소드를 말하는데 이에 대한 예시를 다루기에는 내용이 방대해지므로 추후 별도로 다루기로 하겠다.

이는 JCF의 Stack 클래스와 유사하게 수행되지만, Stack 클래스의 초기 용량 설정 부족 문제를 해결했다.

 

Stack은 초기 용량을 설정할 수 있는 생성자가 없기 때문에 데이터의 삽입이 많아지면 배열을 복사하는 상황이 빈번하게 발생한다. ArrayDeque는 생성자로 배열의 초기 크기를 지정할 수 있고 용량이 초과하면 기존 용량을 2배로 늘려주거나 줄여주는 로직이 존재한다.

 

1. 어떤 구현체를 사용할까

멀티스레드 환경과 상관 없이 자바에서의 Stack은 대부분의 조건에서 성능 저하를 일으키기 때문에 사용을 지양한다.

대신 Deque의 구현체를 사용한다.

 

일반적으로 사용하는 Deque의 구현체는 ArrayDeque와 LinkedList가 있다. 둘의 차이점을 살펴보자.

 

  • ArrayDeque는 Deque 인터페이스의 구현체이며 크기를 재설정할 수 있다.
  • LinkedList는 List의 구현체이다.
  • LinkedList는 null 요소를 추가할 수 있지만 ArrayDeque는 불가능하다.
  • LinkedList는 반복 중에 현재 요소를 제거하는 것이 효율적이고, ArrayDeque는 양쪽 끝에서 추가, 제거가 효율적이다.
  • LinkedList는 ArrayDeque보다 더 많은 메모리를 소모한다.
  • 메모리 소모량이 적을 때는 Iterate 효율이 좋은 ArrayDeque를 사용하고, Stack의 사이즈가 커지거나 심한 변동이 예상될 때는 즉각적인 메모리 공간 확보를 위해 LinkedList를 사용한다.

 

2. 멀티스레드 환경

멀티스레드 환경에서는 스레드로부터 안전한 Deque를 사용해야 한다. 이 경우에는 각각 LinkedBlockingDeque와 ConcurrentLinkdDeque를 사용하면 된다.

 

둘은 Thread-Safe하다는 공통점이 있지만, 동시 잠금 동작 측면에서 차이점이 있다.

 

LinkedBlockingDeque는 잠금 메커니즘을 사용하여 한 번에 단일 스레드에서만 데이터를 작동할 수 있도록 할 때 사용한다. ConcurrentLinkdDeque는 각각의 스레드가 공유 데이터에 액세스할 수 있도록 할 때 사용한다. 또한, 데이터를 작동할 때 성능에 영향을 미칠 수 있다는 차이점이 있다.

 

3. 결론

대부분의 상황에서는 Deque를 사용할 때 LinkedList 보다는 ArrayDeque를 사용하면 된다. 또한 멀티스레드 환경에서 단일스레드를 사용할 계획이라면 LinkedBlockingDeque를 사용하고 멀티스레드를 사용할 계획이라면 ConcurrentLinkdDeque를 사용하면 된다.

 

 

🙏 :: 참조

반응형