2011-03-23 4 views
3

내가 자바 응용 프로그램의 메모리 할당 및 멀티 스레딩에 관해서 몇 가지 디자인을 통해 생각하기 위해 노력하고있어이 내가 궁금하네요 무엇 :는 컬렉션 대 자바 배열을 반환

나는 동기화 된 컬렉션을 가진 클래스가 두 번째로 여러 번 업데이트되는 목록을 말하지만 클래스 내에서 모든 업데이트가 발생하고 다른 스레드에서 자체 스레드가 발생하지 않습니다. 그러나 getCollection() 메서드를 호출하고 foreach를 사용하여 내용을 읽기 전용으로 반복하는 다른 많은 스레드가 있습니다. 이것은 내가 모르는 것입니다 :

다른 스레드가 동기화 된 colletion을 반복하는 경우 업데이트를 수행하는 단일 스레드는 다른 스레드가 반복하지 않는 시점까지 기다려야합니까?

두 번째 질문은 .toArray를 사용하여 컬렉션 자체가 아니라 컬렉션의 배열 복사본을 반환하는 것이 합리적이라고 생각하지만 메모리 관점에서 생각하면 새로운 배열을 할당해야합니다. 그것은 매번 컬렉션 내용의 크기이고 수천 개의 객체가있는 콜렉션에서 두 번째로 수백 번 호출되는 경우에는 모르는 내용입니다.

또한 목록을 동기화하는 것보다 컬렉션 자체를 반환하지 않으면 더 이상 필요하지 않습니다.

모든 입력을 부탁드립니다. 감사! - 던컨

답변

6

CopyOnWriteArrayList를 사용하는 것이 좋습니다. 이것은 스레드로부터 안전하며 임의의 수의 스레드로 효율적으로 액세스 할 수 있습니다. 업데이트 수가 적 으면이 상태가 좋습니다.

그러나 질문에 대답하십시오. 수정 중일 때 동기화 된 콜렉션을 반복하는 경우 ConcurrentModificationException이 발생합니다 (COWAL에서는이 문제가 발생하지 않음). 업데이트가이 작업으로 인해 차단되지는 않지만 독자 만 문제가됩니다.

getCollection이 호출 될 때마다 복사본을 만드는 대신 컬렉션이 수정 될 때마다 복사본을 만듭니다 (훨씬 적은 빈도로). COWAL이 수행하는 작업입니다.

요청에 따라 복사본을 반환하는 경우에도 컬렉션을 동기화해야합니다.

10

다른 스레드가 더 다른 스레드가 반복되지 않을 때 업데이트가 을 수행하는 하나의 스레드가 특정 시점까지 기다려야합니다 동기화 colletion을 반복하는 경우?

동시 (비 동시) 모음에 대해서는 '예'입니다. 두 번째 질문은 은 java.util.concurrent.CopyOnWriteArrayList의 실제 사용 사례처럼 보입니다.

+0

+1 : 나에게 너무 빠릅니다. ;) –

2

아마도 가장 쉬운 방법은 두 개의 컬렉션 (클래스 자체로 업데이트되는 컬렉션)과 getCollection()이 호출 될 때 반환되는 휘발성 필드의 읽기 전용 복사본을 유지하는 것입니다.

후자는 해당 할 때 주 컬렉션을 업데이트하는 프로세스에 의해 다시 만들어야합니다. 이렇게하면 컬렉션을 원자 적으로 업데이트 할 수 있습니다. 한 번에 여러 요소를 변경하고 중간 상태를 숨길 수 있습니다.

업데이트가 자주 발생하지 않고 모든 업데이트가 일관된 상태로 컬렉션을 떠나는 경우 이미 제안 된 CopyOnWriteArrayList를 사용하십시오.

0

콜렉션이 자주 업데이트되고 #getCollection()이 자주 호출되는 것으로 보입니다. CopyOnWriteArrayList를 사용할 수 있지만 배열을 수정할 때마다 복사본을 만듭니다. 따라서 성능이 어떻게 영향을 미치는지 확인해야합니다.

또 다른 옵션은 클래스 내의 스레드가 #getCollection이 호출 될 때마다 복사본을 만들어 작업하는 것입니다. 내부 클래스 스레드가 완료 될 때까지 기다리는 #getCollection이 포함됩니다.

#getCollection이 최신 복사본이 아닌 최신 복사본을 반환하도록하려면 내부 스레드가 주기적으로 #getCollection에서 반환 된 컬렉션 복사본을 만들도록 할 수 있습니다. 복사본은 휘발성이거나 AtomicReference이어야합니다.