2010-03-01 3 views
1

내 문제를 제공한다. java-doc은이 컨테이너가 fail-fast 반복기만을 제공한다고 말합니다. 그 Iterator 동안 제거 된 요소가있는 경우는 자바 컨테이너가 페일 세이프 (fail-safe) 반복자 여기

유효하지 않는 나에게 Iterator을 제공 자바 Vector 또는 List 같은 표준 컨테이너를 통해 Iterator을 얻을 수있는 가능성이 있는가, (르파되지 않습니다) "삶"?

C++에서 std::list과 같은 동작을해야합니다. 이터레이터는 현재 반복자가 제거 된 경우에도 항상 유효합니다. 이터레이터는 목록의 다음 요소로 설정됩니다.

public class ClientHandle { 
private final Vector<ClientHandleListener> listeners = new Vector<ClientHandleListener>(); 


public synchronized void addListener(ClientHandleListener chl) { 
    listeners.add(chl); 
} 

public synchronized void removeListener(ClientHandleListener chl) { 
    listeners.remove(chl); 
} 

private void fireConnectionClosed() { 
    final ClientHandle c = this; 

    final Iterator<ClientHandleListener> it = listeners.iterator(); 
    new Thread(){ 
     @Override 
     public void run() { 
      while (it.hasNext()) { 
       it.next().connectionClosed(c); //FIXME the iterator gets modified 
      } 
      }; 
    }.start(); 
}} 

public class ClientHandlePool implements ClientHandleListener, TaskManagerListener { 

     /*...*/ 
    public synchronized void removeClientHandle(ClientHandle ch) { 
       //here the listeners Vector from the ClientHandle gets modified 
     ch.removeListener(this); 
     ch.removeListener(currentListener); 
     clientHandles.remove(ch); 
    } 

    @Override 
    public void connectionClosed(ClientHandle ch) { 
     removeClientHandle(ch); 
    } 
} 
+1

문제는 벡터를 사용하여 시작합니다. 벡터는 사용하지 마십시오. 목록, 벡터 및 해시 테이블은 나쁜 연습이고 오래되었습니다. java.util.concurrent 패키지를 참조하십시오. –

+2

@fuzzy :'Vector'와'Hashtable'은 반드시 나쁜 것은 아닙니다. 특정 기능 (대부분 동기화)이 필요할 때 유효한 위치가 있습니다. –

+1

@joachim 그래서 퍼지가 이미 말했듯이 java.util.concurrent 패키지가있는 것입니다. CopyOnWriteArrayList는 동시 수정을 처리해야 할 때 매우 유용합니다. -* edit * : 기본적으로 List/Map/Set/등의 동기화 사본을 만드는 java.util.Collections.synchronizedXYZ 메소드가 있습니다. 스레드 세이프 래퍼를 사용하는 스레드 안전 목록 또는 맵이 필요한 경우에도 – Tedil

답변

8

내가 아는 한 실제로 모든 기능을 소급하여 추가 할 수있는 방법이 없습니다. Collection 구현 (사실 Iterable).

그러나 iterating하는 동안 동시 수정에 대한 응답을 잘 정의함으로써 이러한 종류의 동작을 지원하는 구현이 있습니다.

하나의 예가 CopyOnWriteList입니다.

+0

+1 : CopyOnWriteList는 제가 제안하려고했던 것입니다. –

+0

+1 감사합니다. 내 문제를 해결 한 – nutario

2

java.util.concurrent 패키지를 보면 필요한 모든 것을 찾을 수 있습니다.

6

청취자의 경우 일반적으로 쓰기보다 읽기가 더 많으므로 java.util.concurrent.CopyOnWriteArrayList을 사용하는 것이 좋습니다.

0

빠르고 안전한 페일 세이프 반복자를 만드는 게으른 방법입니다. 잠긴 상태에서 배열의 복사본을 배열로 가져오고 잠금 해제 된 상태에서 배열을 foreach()합니다. 모든 유형의 목록으로 수행 할 수 있습니다

private void fireConnectionClosed() { 
    final ClientHandle c = this; 

    final ClientHandleListener[] listenersArr; 
    synchronized(this) { 
     listenersArr=listeners.toArray(new ClientHandleListener[0]); 
    } 
    new Thread(){ 
     @Override 
     public void run() { 
      for(ClientHandleListener listener : listenersArr) 
       listener.connectionClosed(c); 
      } 
     }; 
    }.start(); 
}