2012-10-21 2 views
0

안녕하세요. 재귀. .pdf URL 수확을하려고 해요. 그리고 ConcurrentModificationException 받고 있어요. 어떻게 이런 일이 있는지 이해하지 못하고 동시성에 대해 많이 몰라요. ; 이것이 어떻게 일어나고 어떻게 고정 될 수 있는지에 대한 약간의 통찰력에 크게 감사 할 것입니다. 주요 통화와URL 수확기 동시성 문제, ConcurrentModificationException

public class urlHarvester { 
    private URL rootURL; 
    private String fileExt; 
    private int depth; 
    private HashSet<String> targets; 
    private HashMap<Integer, LinkedList<String>> toVisit; 

public urlHarvester(URL rootURL, String fileExt, int depth) { 
    this.rootURL = rootURL; 
    this.fileExt = fileExt; 
    this.depth = depth; 
    targets = new HashSet<String>(); 
    toVisit = new HashMap<Integer, LinkedList<String>>(); 
    for (int i = 1; i < depth + 1; i++) { 
     toVisit.put(i, new LinkedList<String>()); 
    } 
    doHarvest(); 
} 

private void doHarvest() { 
    try { 
     harvest(rootURL, depth); 
     while (depth > 0) { 
      for (String s : toVisit.get(depth)) { 
       toVisit.get(depth).remove(s); 
       harvest(new URL(s),depth-1); 
      } 
      depth--; 
     } 
    } catch (Exception e) { 
     System.err.println(e); 
     e.printStackTrace(); 
    } 
    for (String s : targets) { 
     System.out.println(s); 
    } 

} 

private void harvest(URL url, int depth) { 
    try { 
     URLConnection urlConnection = url.openConnection(); 
     InputStream inputStream = urlConnection.getInputStream(); 
     Scanner scanner = new Scanner(new BufferedInputStream(inputStream)); 
     java.lang.String source = ""; 
     while (scanner.hasNext()) { 
      source = source + scanner.next(); 
     } 
     inputStream.close(); 
     scanner.close(); 

     Matcher matcher = Pattern.compile("ahref=\"(.+?)\"").matcher(source); 
     while(matcher.find()) { 
      java.lang.String matched = matcher.group(1); 
      if (!matched.startsWith("http")) { 
       if (matched.startsWith("/") && url.toString().endsWith("/")) { 
        matched = url.toString() + matched.substring(1); 
       } else if ((matched.startsWith("/") && !url.toString().endsWith("/")) 
         || (!matched.startsWith("/") && url.toString().endsWith("/"))) { 
        matched = url.toString() + matched; 
       } else if (!matched.startsWith("/") && !url.toString().endsWith("/")) { 
        matched = url.toString() + "/" + matched; 
       } 
      } 
      if (matched.endsWith(".pdf") && !targets.contains(matched)) { 
       targets.add(matched);System.out.println("ADDED"); 
      } 
      if (!toVisit.get(depth).contains(matched)) { 
       toVisit.get(depth).add(matched); 
      } 
     } 
    } catch (Exception e) { 
     System.err.println(e); 
    } 
} 

클래스 :

urlHarvester harvester = new urlHarvester(new URL("http://anyasdf.com"), ".pdf", 5); 
+0

많은 : 당신은 당신의 수집에서 직접 제거하기의 반복자를 대신 사용할 수 있습니다

for (String s : toVisit.get(depth)) { toVisit.get(depth).remove(s); <---- ... 

:

당신이 toVisitHashMap에서 항목을 제거하려고 할 때 무슨 일이 일어나고 코드 이 문제가 발생한 정확한 행과 전체 소스 파일에 대한 링크를 게시해야합니다. 나는 문제가'doHarvest()'메소드에 있다고 가정한다. 컬렉션을 반복하고 컬렉션에서 요소를 동시에 제거 할 수는 없습니다. 그 때 당신은'ConcurrentModificationException'을 얻습니다. –

답변

5

오류는 아마 동시성과 아무 상관이 없지만,이 루프로 인해 발생 :

for (String s : toVisit.get(depth)) { 
    toVisit.get(depth).remove(s); 
    harvest(new URL(s),depth-1); 
} 

것은 수집하는 동안에서 항목을 제거하려면 iterating, 당신은 반복기에서 remove 메서드를 사용해야합니다 :

List<String> list = toVisit.get(depth); //I assume list is not null 
for (Iterator<String> it = list.iterator(); it.hasNext();) { 
    String s = it.next(); 
    it.remove(); 
    harvest(new URL(s),depth-1); 
} 
1

ConcurrentModificationException은 반복하는 동안 컬렉션을 직접 형성하는 개체를 제거하려고 할 때 throw됩니다.

Iterator<String> iterator = toVisit.get(depth).iterator(); 
while (iterator.hasNext()) { 
    String s = iterator.next(); 
    iterator.remove(); 
    harvest(new URL(s),depth-1); 
}