출처 : http://blog.naver.com/turbo1117/20018507926
대부분의 사람들이 아무 생각없이 Vector와 Hashtable을 사용하지요.
그러다가 Collection API를 쓰게될 경우 다시금 Vector와 Hashtable에 대해
생각을 하게됩니다. 이놈은 Collection API와 어떤관계지 ? 이렇게.
아래는 Vector와 Hashtable에 공히 적용되는 이야기입니다.
메소드들이 synchronized가 되어 있는것은 아시겠지만,
쓰레드 동기화 때문이지요. 즉, Vector와 Hashtable은
태생적으로 쓰레드 세이프한 클래스들입니다. 그래서, 지금껏
아무 생각없이 썼어도 뻑이 안나고 잘 돌았던거지요.
따라서 Vector와 Hashtable은 멀티 쓰레드환경에서 사용시
쓰레드 세이프한 녀석들이다 ..이렇게 알고 계시면 됩니다.
버뜨, Collection API가 출몰하면서, 상황이 쬐금 미묘하게 변했습니다.
Collection API는 대학시절 배우셨던, Map이나 Set이니 List니 이딴것들을
자바에서 쉽게 사용할 수 있도록 만든 자바 클래스 라이브러리라보시면 됩니다.
근데, Collection API가 출몰하면서 Vector는 List를, Hashtable은 Map을 각각
implements하면서 Collection API 안으로 들어갔습니다.
즉, Collection 라이브러리의 범주에 포함되면서,
기존의 Vector와 Hashtable을 사용하던 방식과,
Collection API로 이용하는 방식 두가지 모두 가능하게 되었다는 거지요.
즉, Enumeration enum = Vector.elements()로 사용해도 되고,
Iterator it = Vector.iterator()를 사용하거나,
인터페이스 List에 있는 메소드를 통해 사용할 수도 있습니다.
여기서 문제되는것은 기존 방식처럼 사용할때면,
멀티 쓰레드 환경에서 아무 문제가 없습니다.
왜냐, 기본적으로 Vector의 모든(Collection API의 메소드를 제외한)가
synchronized되어 있기 때문에 쓰레도 세이프하면서, 아울러
Enumeration 인터페이스 자체는 조회이외는 없기 때문입니다.(삭제 추가 등이 없다)
그러나, Vector나 Hashtable이 Collection 라이브러리에 포함되면서,
List나 Iterator를 통해 Vector나 Hashtable을 사용할 경우,
특히 Vector나 Hashtable의 element들을 삭제나 추가할 경우,
멀티 쓰레드 환경에서 문제가 발생할 수 있습니다.
즉, Collection 라이브러리는 기본적으로 쓰레드 세이프하지 않습니다.
Vector와 Hashtable는 쓰레드 세이프하지만,
Collection API를 통해서 이들을 다룰 경우에는 쓰레드 동기화 문제를 염두해야
한다는 겁니다.
그럼, Collection API 들은 왜 쓰레드 세이프하게 만들지 않았을까요 ?
성능때문이라 생각됩니다. synchronized를 쓰면 성능 저하가 된다는 건 아시죠 ?
synchronized를 붙이면, (어디에 붙이냐에 따라 또 성능이 달라지지만, 메소드에 선언
하느냐, 메소드 안에 블럭으로 선언하느냐에 따라 바이트 코드의 크기가 달라지지만)
Lock관리며, Exception 관리를 위한 부분 등이 추가되어,
바이트코드가 커지며 아울러 성능 또한 저하됩니다.
멀티 쓰레드 환경이 아닌 바에야 굳이 synchronized를 붙힌 성능 나쁜 녀석을
쓸 이유가 없겠죠 ? 뒤집어 얘기하면, 혼자쓰는 프로그램이나 확실히
멀티 쓰레드 환경이 아닌경우에, Vector와 Hashtable을 쓰는것은
불필요하게 Lock을 걸고 풀고 하는 overhead를 유발하여 성능이 떨어집니다.
이 경우, Vector대신에 List나 ArrayList를, Hashtable 대신에 HashMap을
사용하면 불필요한 오버헤드를 줄일수 있습니다.
그럼, Collection 라이브러리 쓸려면 항상 쓰레드 동기화 걱정해야 되냐 ?
당근! 아닙니다. Collection 라이브러리 중에 Collections라는 일종의 Factory(?)
가 있습니다. 이놈이 동기화된(synchronized)된 버전의 List니 Map이니
이런걸 만들어 줍니다.
즉, Vector 처럼 synchronized된 Collection 라이브러리 List를 쓰고 시퍼여 ?
그러면, List list = Collections.synchronizedList( new ArrayList());
이렇게 하여 synchronized된 List를 얻어 동기화 걱정없이 사용할 수 있지요.
참고로, 이 Collections 클래스는 데코레이터 패턴에 해당됩니다.
내부적으로는 ArrayList처럼 동기화안된 Collection라이브러리의 메소드를 호출하여
일을 시키지만, 동기화라는 껍데기를 통해 서비스(일종의 View)를 제공하는 거지요.
대부분의 사람들이 아무 생각없이 Vector와 Hashtable을 사용하지요.
그러다가 Collection API를 쓰게될 경우 다시금 Vector와 Hashtable에 대해
생각을 하게됩니다. 이놈은 Collection API와 어떤관계지 ? 이렇게.
아래는 Vector와 Hashtable에 공히 적용되는 이야기입니다.
메소드들이 synchronized가 되어 있는것은 아시겠지만,
쓰레드 동기화 때문이지요. 즉, Vector와 Hashtable은
태생적으로 쓰레드 세이프한 클래스들입니다. 그래서, 지금껏
아무 생각없이 썼어도 뻑이 안나고 잘 돌았던거지요.
따라서 Vector와 Hashtable은 멀티 쓰레드환경에서 사용시
쓰레드 세이프한 녀석들이다 ..이렇게 알고 계시면 됩니다.
버뜨, Collection API가 출몰하면서, 상황이 쬐금 미묘하게 변했습니다.
Collection API는 대학시절 배우셨던, Map이나 Set이니 List니 이딴것들을
자바에서 쉽게 사용할 수 있도록 만든 자바 클래스 라이브러리라보시면 됩니다.
근데, Collection API가 출몰하면서 Vector는 List를, Hashtable은 Map을 각각
implements하면서 Collection API 안으로 들어갔습니다.
즉, Collection 라이브러리의 범주에 포함되면서,
기존의 Vector와 Hashtable을 사용하던 방식과,
Collection API로 이용하는 방식 두가지 모두 가능하게 되었다는 거지요.
즉, Enumeration enum = Vector.elements()로 사용해도 되고,
Iterator it = Vector.iterator()를 사용하거나,
인터페이스 List에 있는 메소드를 통해 사용할 수도 있습니다.
여기서 문제되는것은 기존 방식처럼 사용할때면,
멀티 쓰레드 환경에서 아무 문제가 없습니다.
왜냐, 기본적으로 Vector의 모든(Collection API의 메소드를 제외한)가
synchronized되어 있기 때문에 쓰레도 세이프하면서, 아울러
Enumeration 인터페이스 자체는 조회이외는 없기 때문입니다.(삭제 추가 등이 없다)
그러나, Vector나 Hashtable이 Collection 라이브러리에 포함되면서,
List나 Iterator를 통해 Vector나 Hashtable을 사용할 경우,
특히 Vector나 Hashtable의 element들을 삭제나 추가할 경우,
멀티 쓰레드 환경에서 문제가 발생할 수 있습니다.
즉, Collection 라이브러리는 기본적으로 쓰레드 세이프하지 않습니다.
Vector와 Hashtable는 쓰레드 세이프하지만,
Collection API를 통해서 이들을 다룰 경우에는 쓰레드 동기화 문제를 염두해야
한다는 겁니다.
그럼, Collection API 들은 왜 쓰레드 세이프하게 만들지 않았을까요 ?
성능때문이라 생각됩니다. synchronized를 쓰면 성능 저하가 된다는 건 아시죠 ?
synchronized를 붙이면, (어디에 붙이냐에 따라 또 성능이 달라지지만, 메소드에 선언
하느냐, 메소드 안에 블럭으로 선언하느냐에 따라 바이트 코드의 크기가 달라지지만)
Lock관리며, Exception 관리를 위한 부분 등이 추가되어,
바이트코드가 커지며 아울러 성능 또한 저하됩니다.
멀티 쓰레드 환경이 아닌 바에야 굳이 synchronized를 붙힌 성능 나쁜 녀석을
쓸 이유가 없겠죠 ? 뒤집어 얘기하면, 혼자쓰는 프로그램이나 확실히
멀티 쓰레드 환경이 아닌경우에, Vector와 Hashtable을 쓰는것은
불필요하게 Lock을 걸고 풀고 하는 overhead를 유발하여 성능이 떨어집니다.
이 경우, Vector대신에 List나 ArrayList를, Hashtable 대신에 HashMap을
사용하면 불필요한 오버헤드를 줄일수 있습니다.
그럼, Collection 라이브러리 쓸려면 항상 쓰레드 동기화 걱정해야 되냐 ?
당근! 아닙니다. Collection 라이브러리 중에 Collections라는 일종의 Factory(?)
가 있습니다. 이놈이 동기화된(synchronized)된 버전의 List니 Map이니
이런걸 만들어 줍니다.
즉, Vector 처럼 synchronized된 Collection 라이브러리 List를 쓰고 시퍼여 ?
그러면, List list = Collections.synchronizedList( new ArrayList());
이렇게 하여 synchronized된 List를 얻어 동기화 걱정없이 사용할 수 있지요.
참고로, 이 Collections 클래스는 데코레이터 패턴에 해당됩니다.
내부적으로는 ArrayList처럼 동기화안된 Collection라이브러리의 메소드를 호출하여
일을 시키지만, 동기화라는 껍데기를 통해 서비스(일종의 View)를 제공하는 거지요.