带有HashSet的java.util.ConcurrentModificationException

时间:2014-10-17 19:32:12

标签: java concurrency hashset

我使用this post实现other post和此Konrad Rudolph's proposed algorithm中描述的非确定性有限自动机。

我没有使用C ++多图,而是使用HashSet<Character> [][] transitions数组(这是家庭作业,不能使用Google的番石榴库)。第一维是原始状态,第二维是命运状态,而HashSet定义原点和命运状态之间转换的符号。我的Automaton类的构造函数是:

Automaton (int numberOfStates)
{
    this.numberOfStates = numberOfStates;
    alphabet = new HashSet<>();
    finalStates = new HashSet<>();

    transitions = new HashSet[numberOfStates][numberOfStates];

    for (int i = 0; i < numberOfStates; i++)
    {
        for (int j = 0; j < numberOfStates; j++)
        {
            transitions[i][j] = new HashSet<Character>();
        }
    }
}

这是我使用此转换数组实现的Konrad Rudolph算法:

public String readStringInAutomaton (char[] inputString,
            int initialState)
{
    HashSet<Integer> currentStates = new HashSet<>();
    HashSet<Integer> nextStates = new HashSet<>();

    currentStates.add(initialState);

    // for each char in inputString
    for (int charIndex = 0; charIndex < inputString.length; charIndex++)
    {
        char currentTransitionChar = inputString[charIndex];
        // for each state in currentStates
        for (Integer originState : currentStates)
        {
            // for each transition starting from originState, current
            // char
            for (int destinyStateIndex = 0; destinyStateIndex < numberOfStates; destinyStateIndex++)
            {
                if (transitions[originState][destinyStateIndex]
                        .contains(currentTransitionChar))
                {
                    nextStates.add(destinyStateIndex);
                }
            }
        }
        currentStates = nextStates;
    }
}

我已尝试按照Oracle's HashSet documentation中的建议,用Collections.synchronizedSet(new HashSet<>());替换HashSet的每个实例化。

但是在初始化转换时我得到了一个java.lang.ArrayStoreException:java.util.Collections $ SynchronizedSet。

for (int i = 0; i < numberOfStates; i++)
{
    for (int j = 0; j < numberOfStates; j++)
    {
        transitions[i][j] = Collections
                .synchronizedSet(new HashSet<>());
    }
}

如何避免这些并发异常?

1 个答案:

答案 0 :(得分:5)

您的问题不是关于多线程,而是关于迭代Set继续添加元素。

您拥有currentStates = nextStates,然后在您的for循环for (Integer originState: currentStates)nextStates.add(destinyStateIndex) {nextStatescurrentStates正在执行相同的实例!) - 分配nextStates

您应该更正算法:nextStates必须根据您使用它的方式在循环中的某处重新分配。