添加项目时,我收到ConcurrentModificationException

时间:2014-06-04 17:32:34

标签: java jsf liferay

我试图将不同经理的经理ID从collab保存到managersId,但我得到一个例外“ConcurrentModificationException”

public void fillTree() throws SystemException, PortalException {

        TreeNode nodeParent;
        TreeNode nodeFils;
        Set<Long> managersId = new HashSet<Long>();
        UserVO user = new UserVO();
        collabs = CollabLocalServiceUtil.getCollabs(-1, -1);
        Iterator<Long> iter = managersId.iterator();
        long id;
        for (int i = 0; i < collabs.size(); i++) {
            id = collabs.get(i).getManagerId();
            synchronized (managersId) {
                managersId.add((Long) id);
                System.out.println(id);

            }

        }



        while (iter.hasNext()) {
            id = iter.next();//throw exeption
            user = getUserById(id);
            nodeParent = new DefaultTreeNode(user.getFullName(), root);
            for (int j = 0; j < collabs.size(); j++) {
                if (collabs.get(j).getManagerId() == user.getUserId()) {

                    nodeFils = new DefaultTreeNode(getUserById(
                            collabs.get(j).getUserId()).getFullName(),
                            nodeParent);
                }
            }
        }

    }

我正在使用liferay门户网站

1 个答案:

答案 0 :(得分:0)

根据问题更新进行修改。

在这个新代码中,问题出在你的迭代器上。您初始化了迭代器,然后修改了集合,然后尝试使用脏迭代器。这是并发修改异常的原因。 所以解决这个问题很简单。只需在for循环后移动Iterator<Long> iter = managersId.iterator();即可。尝试

public void fillTree() throws SystemException, PortalException {

    TreeNode nodeParent;
    TreeNode nodeFils;
    Set<Long> managersId = new HashSet<Long>();
    UserVO user = new UserVO();
    collabs = CollabLocalServiceUtil.getCollabs(-1, -1);        
    long id;
    for (int i = 0; i < collabs.size(); i++) {
        id = collabs.get(i).getManagerId();
        synchronized (managersId) {
        managersId.add((Long) id);
        System.out.println(id);

        }

    }

    Iterator<Long> iter = managersId.iterator(); // Getting the new iterator with latest value.
    while (iter.hasNext()) {
        id = iter.next();//Now this wont throw exeption
        user = getUserById(id);
        nodeParent = new DefaultTreeNode(user.getFullName(), root);
        for (int j = 0; j < collabs.size(); j++) {
        if (collabs.get(j).getManagerId() == user.getUserId()) {

            nodeFils = new DefaultTreeNode(getUserById(
                collabs.get(j).getUserId()).getFullName(),
                nodeParent);
        }
        }
    }
}

OLD ANSWER

首先,根据您的逻辑,我认为您正在尝试将唯一的经理ID作为列表。在这种情况下,您可以使用Set

至于你当前的问题,如果它在多线程环境中执行,你可以使用像

这样的synchronized块
List<Long> managersId = new ArrayList<Long>();

collabs = CollabLocalServiceUtil.getCollabs(-1, -1);

long id;
for (int i = 0; i < collabs.size(); i++) {
    id = collabs.get(i).getManagerId();
    synchronized (managersId) {
        if (!managersId.contains(id)) {
            managersId.add((Long) id);
        }
    }
}

否则您可以使用java.util.concurrent.CopyOnWriteArrayList进行并发列表操作。

List<Long> managersId = new CopyOnWriteArrayList<Long>();

另外,作为第三个选项,您可以通过集合类

使正常列表同步
Collections.synchronizedList(managersId);