ArrayList
다른 스레드에서 추가하는 동안 한 스레드에서 반복하는 방법은 무엇입니까?
1) 루프를 통해 ArrayList
몇 가지 검사를 수행 하는 스레드가 하나 있습니다.
2) 끝에 추가하는 두 번째 스레드가 ArrayList
있습니다.
두 번째가 실행 중일 때 첫 번째 스레드를 일시 중지하는 세마포어가 있지만 어떻게 구현합니까?
두 번째 스레드가에 무언가를 추가 할 때 ArrayList
첫 번째 스레드는 던지지 않고 일시 중지 된 지점에서 루프를 계속합니다 java.util.ConcurrentModificationException
.
당신가를 사용하는 바인딩하는 경우 ArrayList
당신은 할 필요가 그에 대한 액세스를 동기화 할 수 있습니다. 그러나 이것이 반드시 동시성과 관련이있는 것은 아니기 때문에 ConcurrentModificationExeptions에서 당신을 구할 수는 없습니다.
에서 의 JavaDoc
이 예외가 항상 다른 스레드에 의해 객체가 동시에 수정되었음을 나타내는 것은 아닙니다. 단일 스레드가 개체의 계약을 위반하는 일련의 메서드 호출을 발행하면 개체가이 예외를 throw 할 수 있습니다. 예를 들어 스레드가 fail-fast iterator를 사용하여 컬렉션을 반복하는 동안 컬렉션을 직접 수정하면 반복기가이 예외를 throw합니다.
보장 할 수있는 경우 새 항목 만 목록에 추가되고 인덱스를 사용하고 반복자를 사용하지 않고 수동으로 반복 할 수 있습니다. 대기열 끝에 도달하면 처음부터 다시 시작합니다.
ArrayList q = new ArrayList<>();
//thread 1
Object o = ...;
synchronized(q) {
q.add(o); //append
}
//thread 2
int i = 0;
synchronized(q) {
int size = q.size();
for(; i < size; i++){
Object o = q.get(i);
//do something with o
}
if(i >= size) {
i = 0;
}
}
그러나 그렇게하면 하나 또는 다른 스레드가 목록에서 한 번에 작동 할 수 있으므로 다소 순차적 인 동작으로 이어질 것입니다. 유일한 "장점"은 스레딩 모델이 루프 작업에 임의성을 추가한다는 것입니다. 따라서 동기화 및 동시성을 건너 뛰고
q.add(o); //append
//you may add a random condition, i.e. time interval, item count random number to trigger the loop process so it don't get exectued on each add
for(Object o : q){
//do something with o
}
물론 Nicolas가 작성한 것처럼 Safe-Copy를 사용할 수 있지만 이는 내용이 아닌 컨테이너 구조 (목록)의 얕은 복사본 일뿐입니다. 따라서 그렇게 할 경우 항목이 스레드로부터 안전한지 확인하거나 수정하지 마십시오.
두 번째 스레드가 때때로 목록 끝에서 항목을 제거하는 경우 대기열을 사용하는 것이 좋습니다. Java가이를 제공합니다 Deque
. 한 스레드는 한쪽 끝에 요소를 추가하고 다른 스레드는 다른 쪽에서 제거 할 수 있습니다. 여러 스레드에서 사용하고 수동으로 동기화하면 스레드 안전 구현을 사용하고 동기화를 건너 뛰는 것이 좋습니다.
Deque q = new ConcurrentLinkedDeque<>();
//thread 1
Object o = ...;
q.addFirst(o);
//thread 2
while(!q.isEmpty()){
Object o = q.removeLast();
//do something with o
}
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다