Java并发修改例外:如何处理?

时间:2012-11-17 22:21:28

标签: java exception concurrentmodification

我正在编写一个文本文件爬虫程序,并不断收到ConcurrentModificationException。我知道它与使用Iterator有关,但我不知道如何解决它。请帮忙!

例外是:

Exception in thread "main" java.util.ConcurrentModificationException
        at java.util.LinkedHashMap$LinkedHashIterator.nextEntry(unknown Source)
        at java.util.LinkedHashMap$KeyIterator.next(Unknown Source)
        at TextCrawler.main(TextCrawler.java:112)

代码:

while(it1.hasNext() && wordCount2 < wordCountToFind2) { //while there are more files to be searched and the wordCount is less than max occurrences 
           wordCount2 = 0;
           Iterator it3 = occurrencesVector.iterator();
           while(it3.hasNext()) { //get current wordCount
             wordCount = (Integer)it3.next();
             wordCount2 += wordCount;
             System.out.println("WordCount2...." + wordCount2); //Test
           }
           String nextFile = (String)it1.next(); //this is line 112
           System.out.println("nextFile...." + nextFile + "\n" + "\n"); //Test
           if(i > 0) { //skips the initial input filename (which is at the start of filenameSet) so it's not checked twice
             System.out.println("Start searchFile method"); //Test
             try{txtCr2.searchFile(nextFile, wordToFind2, wordCountToFind, caseSensitive);} //call searchFile method
             catch(IOException e){System.out.println("txtCr2 exception, searchFile method didn't happen!"); e.printStackTrace();};
           }
           i++;
           System.out.println("i = " + i);
         }

searchFile方法的完整代码:

public void searchFile(String filename, String wordTF, String wordCountTF, String caseS) throws IOException
 {
    FileReader aFileReader = new FileReader(new File(filename)); //make the file readable
    BufferedReader aBufferedReader = new BufferedReader(aFileReader);
    String newFile, lineFromFile, updatedLine = "", filePattern = "\\([a-zA-Z0-9]{1,32}.txt\\)", outputMessage = "";
    char aChar;
    int wordCount = 0, occurrencesToFind;
    occurrencesToFind = Integer.parseInt(wordCountTF); //convert passed down String to int
    filenameSet.add(new String(filename)); //add the filename to the LindedHashSet

    while((lineFromFile = aBufferedReader.readLine()) != null) { //while lineFromFile is not empty
      for(int i = 0; i < lineFromFile.length(); i++) { 
        aChar = lineFromFile.charAt(i); //go through each line character by character
        if(Character.isLetterOrDigit(aChar) || Character.isWhitespace(aChar) || aChar == '(' || aChar == ')' || aChar == '.') 
          if(aChar == '(') //if the character is ( then add a space in front of it
            updatedLine = updatedLine +  " " + aChar;  
          else
          if(aChar == ')') //if the character is ) then add a space after it
            updatedLine = updatedLine + aChar + " ";
          else
            updatedLine = updatedLine + aChar; //if the character is a letter, digit or whitespace just add it to the updatedLine
      }    //all unwanted punctuation is removed
    } 
    aFileReader.close();
    aBufferedReader.close();

    String [] fileArray = updatedLine.toLowerCase().split(" "); //split the updatedLine into an array at the whitespaces.

    //for(int i = 0; i < fileArray.length; i++) //Test
      //System.out.println(fileArray[i]);

    boolean fileSearched = false;

    while(wordCount < occurrencesToFind && !fileSearched) { //while the wordCount is less than the required wordCount and the file hasn't been completely searched.
      if(caseS.equals("1")) { //if the word to be checked is case sensitive
        for(int j = 0; j < fileArray.length; j++) { //for the length of the array
          if(fileArray[j].equals(wordTF)) //if a word in the fileArray exactly equals the word to be searched
            wordCount++; //add a count of one to the wordCount
          if(fileArray[j].matches(filePattern)) { //if a word in the fileArray matches the filePattern e.g. (filename.txt)
            newFile = fileArray[j].substring(1,fileArray[j].length() -1); //newFile is equal to the filePattern with round brackets removed.
            System.out.println("New File found..." + newFile); //Test
            filenameSet.add(new String(newFile)); //add it to the LinkedHashSet
          }
        }
        fileSearched = true; //file has been searched
      }
      else { //else if the word to be checked isn't case sensitive
        for(int j = 0; j < fileArray.length; j++) { //for the length of the array
          if(fileArray[j].toLowerCase().equals(wordTF.toLowerCase())) //not case sensitive so make both search word and fileArray word lower case
            wordCount++; //if they are equal add a count of one to the word count
          if(fileArray[j].matches(filePattern)) { //if a word in the fileArray matches the filePattern e.g. (filename.txt)
            newFile = fileArray[j].substring(1,fileArray[j].length() -1); //newFile is equal to the filePattern with round brackets removed.
            System.out.println("New File found...." + newFile); //Test
            filenameSet.add(newFile); //add it to the LinkedHashSet
          }
        }
        fileSearched = true; //file has been searched
      }
    }
    occurrencesVector.addElement(new Integer(wordCount)); //add the wordCount to the occurrences LinkedHashSet
    System.out.println("occurrencesVector contains.." + occurrencesVector); //Test
    System.out.println("filenameSet contains.." + filenameSet);  //Test
    System.out.println("End of searchFile method.\n\n"); //Test
 }

occurrencesVector:

public class TextCrawler
{
 static LinkedHashSet<String> filenameSet = new LinkedHashSet<String>();
 static Vector<Integer> occurrencesVector = new Vector<Integer>();

IT1:

System.out.println("\nStarting initial file search in..." + startFile2);
         try{txtCr.searchFile(startFile2, wordToFind2, wordCountToFind, caseSensitive);}
         catch(IOException e){System.out.println("txtCr exception");};

         boolean nextFileSearched = false;
         int wordCount, wordCount2 = 0, wordCount3, wordCount4 = 0; 
         Iterator it1 = filenameSet.iterator();
         Iterator it2 = occurrencesVector.iterator();
         int i = 0;

         while(it2.hasNext()) { //get current wordCount
           wordCount = (Integer)it2.next();
           wordCount2 += wordCount;
         }

         while(it1.hasNext() && wordCount2 < wordCountToFind2) { //while there are more files to be searched and the wordCount is less than max occurrences 
           wordCount2 = 0;

1 个答案:

答案 0 :(得分:0)

ConcurrentModificationException意味着您正在使用“过期”迭代器。

迭代器已“过期”,因为它当前正在抓取的集合已更改。

这是一个很好的代码示例来演示:

public static void main(String[] ar) {
    LinkedList<Integer> l = new LinkedList<Integer>();

    l.add(1);
    l.add(2);
    l.add(3);

    Iterator<Integer> i1 = l.iterator();

    System.out.println(i1.next());
    System.out.println(i1.next());

    // Here we modify the content of "l"
    l.add(4);

    // After modifying the content of "l" we try to get the next element of the iterator: this will throw an exception
    System.out.println(i1.next());
}