2011-08-02 2 views
159

인덱스를 기준으로 요소에 액세스 할 수있는 동시 List 인스턴스를 만들려면 어떻게해야합니까? JDK에는 사용할 수있는 클래스 나 팩토리 메소드가 있습니까?Java JDK에 동시 목록이 있습니까?

+18

왜 건설적이지 않습니까? .Net에없는 CopyOnWriteArrayList가 여러 제안되었습니다. 두 질문이 서로 관련이 있다고는 말할 수 있지만이 질문을 닫지는 마십시오 !!! –

+0

.NET에서 CopyOnWriteArrayList에 해당하는 것은 불변의 컬렉션입니다. 동시 수집은 (ConcurrentQueue 등) 수정하기 위해 잠금을 필요로하지 않는 컬렉션입니다. 복사 할 때마다 내용을 복사하지 않습니다. –

+1

Jarrod Roberson이 왜 Stephan이 만든 자세한 편집 내용을 원래의 잘못 표현 된 질문으로 되돌려 놓는 것이 좋은 생각이라고 생각하지 않습니다. Jarrod의 대답은 여전히 ​​완벽하게 받아 들일 만합니다. 사실, CopyOnWriteArrayList는 JDK에서 List를 구현하는 유일한 동시 클래스입니다. 의아해했다 ... –

답변

112

java.util.concurrent에는 동시 목록 구현이 있습니다. 특히 CopyOnWriteArrayList. 당신이 필요로하는 모든 간단한 호출 동기화 경우 당신은 아주 잘 Collections.synchronizedList(List)을 사용할 수 있습니다

+53

모든 삽입물에 전체 목록을 복사하므로 종종 비효율적입니다. – dfrankow

+11

@dfrankow 그러나 당신이 업데이트하는 것보다 훨씬 더 반복적이라면 더 * 더 * 효율적일 수 있습니다. –

30

위치를 획득하고 주어진 위치에서 요소를 가져 오는 작업은 자연스럽게 잠금이 필요하기 때문에 (목록에 두 작업간에 구조적 변경이 없어야 함).

동시 수집의 아이디어는 자체적으로 각 작업이 절대적이며 명시 적 잠금/동기화없이 수행 될 수 있다는 것입니다.

그러므로 주어진 List 위치에서 n 위치의 요소를 가져 오는 것은 동시 액세스가 예상되는 상황에서 너무 많은 의미를 갖지 않습니다.

+4

요아킴, 네가 머리에 못을 박은 것 같아. 예를 들어, 읽기 전용 목록을 동시 목록으로 취하십시오. 목록에서 N 위치의 요소를 가져 오는 것은 의미가있을뿐만 아니라 문제의 간단 함을 나타냅니다. 그래서, 불변의 목록 (소문자 L)은 좋은 예가 될 것이지만 그것은 목록 (대문자 L)이 아닙니다. CopyOnWriteArrayList는 동시 발생하지만 많은 사람들은 성능이 마음에 들지 않습니다. 로프 (문자열 로프)의 라인을 따라 솔루션은 아마 좋은 승자가 될 것입니다. – johnstosh

+0

아주 좋은 지적. 그러나 OP가 사용하는 목록에는 매우 구체적인 사용법이있을 수 있습니다. 예 : 동시 환경에서 채워질 수 있으며, "잠긴"(의미가 무엇이든간에) 다음 인덱스로 안전하게 액세스 할 수 있습니다. 따라서, 이러한리스트를 작성하는 첫 단계에서는 스레드 안전 구현이 여전히 필요합니다. 불행히도, OP는 그가 찾고있는 목록이 어떻게 사용될 것인지에 대해서는 구체적이지 않았습니다. –

90

:

List<Object> objList = Collections.synchronizedList(new ArrayList<Object>()); 
+43

'synchronizedList'의 결과는 "synchronized"이지만 "concurrent"는 아닙니다. 하나의 근본적인 문제는 인덱스 기반 인 많은 List 연산 자체가 원자 적이지 않고 더 큰 상호 배타 구조의 일부일 필요가 있다는 것입니다. –

+3

IMO,'Vector'는'Collections.synchronizedList (new ArrayList ())'보다 더 직관적입니다. – Stephan

+4

synchronizedList의 결과는 "synchronized"이지만 "concurrent"는 아닙니다. –

95

당신은 인덱스 기반 액세스를하는 것에 대한 걱정 그냥하지 않으려면 삽입 순서 보존 (A)의 특성을 목록에서 java.util.concurrent.ConcurrentLinkedQueue을 고려해 볼 수 있습니다. Iterable을 구현 했으므로 모든 항목을 추가하고 나면 각 단순 구문을 사용하여 내용을 반복 할 수 있습니다.

Queue<String> globalQueue = new ConcurrentLinkedQueue<String>(); 

//Multiple threads can safely call globalQueue.add()... 

for (String href : globalQueue) { 
    //do something with href 
} 
+3

단순화 된 for 문 (':')은 foreach라고합니다. http://docs.oracle.com/javase/1.5.0/docs/guide/language/foreach.html –

+2

@ AlikElzin-kilaka 권리. 실제 구문에는 "each"라는 단어가 포함되어 있지 않기 때문에 그 이름이 항상 나를 괴롭혔다 고 생각합니다. 그러나 공식 이름을 사용하도록 답변을 업데이트하겠습니다. :) –

+2

@ AlikElzin-kilaka Nitpicking하지만 [JLS 버전 8] (https://docs.oracle.com/javase/specs/jls/se8/html/jls-14.html#jls-14.14.2)에 따르면) "향상된 for 문"이라고합니다. [java 튜토리얼] (https://docs.oracle.com/javase/tutorial/java/nutsandbolts/for.html)에서도 마찬가지입니다. – Roland

관련 문제