2

나는이 코드는 부두 웹 서버 내에서 실행되는 특정 접두사자바 속성 variabile : 설정 특성 동안 반복 키

private static List<String> getKeysByPrefix(String prefix) { 
    Set<?> keySet = System.getProperties().keySet(); 
    Iterator<?> iterator = keySet.iterator(); 

    List<String> list = new ArrayList<>(); 
    while (iterator.hasNext()) { 
     String key = (String) iterator.next(); 

     if (key.startsWith(prefix)) { 
      list.add(key); 
     } 
    } 

    return list; 
} 

로 시작하는 모든 시스템 속성 키를 수집하는 코드를 가지고 있고, 반면 요청이이 코드를 실행 중입니다. 다른 요청이 java 내부에 새로운 키를 작성하는 경우가 발생할 수 있습니다. System.setProperty("test", "foo");

이 시나리오에서는 속성을 반복하고 다른 요청이 변경되는 동안 ConcurrentModificationException이 표시됩니다. 그것.

java.util.ConcurrentModificationException 
    at java.util.Hashtable$Enumerator.next(Hashtable.java:1378) 

새로운 속성이 키를 반복하는 일에 비해 완전히 다른 흐름이지만, SystemProperties는 모든 JVM 인스턴스 공유하고 있기 때문에, 나는이 오류를 받고 있어요 설정 코드입니다.

이 주제를 다루는 다른 주제를 이미 발견했으며 가장 권장되는 솔루션은 ConcurrentHashMap을 사용하고 있습니다. 이 옵션은 SystemProperties 맵을 생성하는 것이 아니기 때문에 읽을 수는 없기 때문에 나에게 유용하지 않습니다. 당신은 단순히 바로이 문제를 해결하기 위해 제안 된 연습을 여기 반복자 루프

의 폐쇄 브래킷 전에 setProperty 전화를 추가 할 수 있습니다 문제를 재현하기 위해

?

+0

주어진 시간에 시스템 속성을 수정할 수있는 스레드가 하나만 있으면됩니다. – Mena

+0

속성을 어떻게 업데이트합니까? 'System.setProperty' 사용하기? – manouti

답변

0

목록을 반복하는 동안은 목록을 변경할 수 없습니다.

두 가지 옵션 :

는 CopyOnWriteArraySet 이것을보십시오 :

Set<?> keySet = new CopyOnWriteArraySet<Object>(System.getProperties().keySet()); 
    Iterator<?> iterator = keySet.iterator(); 

    List<String> list = new ArrayList<String>(); 
    while (iterator.hasNext()) { 
     String key = (String) iterator.next(); 

     if (key.startsWith(prefix)) { 
      list.add(key); 
     } 
    } 

    return list; 
+1

두 번째 요점에 대해서, 여기서 문제는 반복 이후에 수정이 적용되지 않는다는 것입니다. 두 개의 서로 다른 e 개의 분리 된 흐름입니다. –

+0

따라서 java.util.concurrent 패키지 유형 (예 : CopyOnWriteArraySet http://docs.oracle.com/javase/7/docs/api/java/util)에서 루프를 시작하거나 원래 세트를 캡슐화하기 전에 목록을 복제해야합니다. /concurrent/CopyOnWriteArraySet.html) – fandango

+0

문제는 컬렉션을 복제 할 때 'HashTable'속성을 반복하기 때문에 OP와 동일한 문제가 발생할 수 있다는 것입니다. – Gray

0

난 당신이 잠금 개체를 만들고 속성이 객체에 읽기/쓰기하려고 할 때마다 synchronized 블록을 사용해야한다고 생각합니다. 내가 속성을 반복하고있어 또 다른 요청을 변경하는 동안이 ConcurrentModificationException를 얻고이 시나리오와

public final Object systemPropLockObject = new Object(); 

synchronized (systemPropLockObject) { 
    // write the code to read/write to the system properties 
} 
0

.

이 오류는 System 속성을 부적절하게 사용하고 있다고 말합니다. 그들은 HashTable에 의해 뒷받침 되더라도 동시에 반복되고 업데이트되도록 설계되지 않았습니다.관통 맵이 변경되었을 경우, 세트의 반복이 진행되는 동안 반복자 자신의 remove 오퍼레이션을 제외 (

, 또는 :

HashTable 코드를 찾고에서 내가 좋아하는 의견을 많이 볼 반복자에 의해 반환 된지도 엔트리의 setValue 연산) 반복 결과는 정의되지 않습니다.

앉아서하는 것은 불필요합니다.

이 주제를 다루는 다른 주제를 이미 발견했으며 가장 권장되는 솔루션은 ConcurrentHashMap을 사용하고 있습니다. 이 옵션은 SystemProperties 맵을 생성하는 것이 아니기 때문에 읽을 수는 없기 때문에 나에게 유용하지 않습니다.

CHM을 초기 시스템 등록 정보 맵의 내용으로 초기화하지만 CHM으로 읽거나 쓰는 공유 클래스를 가질 수 없습니까?

속성을 이야기하지 않고 질문을 편집하고 필요에 대해 이야기하면 더 나은 답변을 찾을 수 있습니다. 당신이 필사적 경우

는 마지막으로, 당신의 반복 수도 작업 주위에 잠금 :

Properties props = System.getProperties(); 
List<String> list = new ArrayList<>(); 
synchronized (props) { 
    // get the properties which match with an enumeration inside the lock 
    ... 
} 

이 시스템의 특성 자체를 잠그는 방법에 대한 톤을 달려 있지만, 이것은 당신을 위해 작동 할 수 있습니다. CHM으로 다른 솔루션을 구현하는 것이 나에게 좋을 것 같습니다.