首页 > 解决方案 > Java:损坏的 ArrayList?

问题描述

我有一个 REST 项目,我在其中将一个ArrayList用户保留在访问控制服务类中。一切正常,直到 REST Web 服务突然抛出一个java.util.NoSuchElementException. 浏览代码,我意识到这ArrayList很奇怪:

  1. 在逐步执行原因期间将鼠标悬停在 Eclipse 中的字段上com.sun.jdi.InvocationException occurred invoking method.。经过一些研究,似乎在toString()定义不正确时会发生这种情况。好吧,我不确定这里的错误是什么意思。
  2. 的大小ArrayList-1

重新启动服务器后问题消失了,但我需要知道是什么导致了这种情况发生。有人有什么想法吗?

编辑

有人要求提供代码,所以我将粘贴与列表相关的部分。

@Service
@Transactional
public class AccessControlServiceImpl implements AccessControlService {
    @Autowired
    private OnlineUserTracker userTracker;

    @Autowired
    private UserDAO userDao;

    public boolean checkAuthorized(String username) {
        User user = userDao.findById(username);

        // Other logic
        userTracker.getUsers().add(user); // If user is authorized
    }

    public void logoff(String username) {
        userTracker.removeUser(username);
    }
}

public class OnlineUserTracker {
    private List<User> users;

    public OnlineUserTracker() {
        this.users = new ArrayList<>();
    }

    public List<User> getUsers() {
        return users;
    }

    public void setUsers(List<User> users) {
        this.users = users;
    }
    
    public User getUserFromUsername(String username) {
        for (User user : users) {
            if(user.getUsername().equals(username)) {
                return user;
            }
        }
        return null;
    }

    public void removeUser(String username) {
        User user = getUserFromUsername(username);
        if (user != null) {
            users.remove(user);
        }
    }
}

标签: javaeclipserestarraylist

解决方案


假设问题是不正确的并发,一个好的解决方案是将所有与列表的交互包装在 OnlineUserTracker 中,然后同步相关方法(这意味着没有方法应该返回底层列表)。事实上,无论您如何解决问题,最好不要将 List 暴露给 OnlineUserTracker 之外的代码(即封装)。

一个“简单”的解决方案是使 List 成为 CopyOnWriteArrayList 的一个实例。此实现对于正常交互和迭代都是线程安全的。但是,如果您经常添加或删除用户,则效率可能会降低。


推荐阅读