跨插槽连接的ArrayList并发

min*_*olf 5 java sockets multithreading arraylist

我有一个问题.我的信念是,它与并发或线程同步有关,尽管我无法理解正在发生的事情.

这是我对FriendRequestList对象的数据流的描述.

从客户端,我们向另一个用户(工作人员)发送朋友请求.所以我们发送请求并将自己的用户名添加到他们的列表中User.incFriendReq.该实例只是一个ArrayList很好的参考.

所以现在我们将请求发送到服务器以接收我们自己的朋友请求列表(FriendRequestList.java).

所以现在问题.如果我在下面使用此代码,则用户在终止其连接(注销)之前将不会看到朋友请求,这将关闭连接.当他登录时,他只会在他的列表中看到该请求.

服务器端代码:

...... Worker.java ......

private Object getFriendRequests() {
    User me = Data.getUser(myUserName);
    if ( me == null ) {
        return new NoSuchUserException(); // Don't worry about it ;)
    }

    return new FriendRequestList(me.getFriendReq());
}
Run Code Online (Sandbox Code Playgroud)

... User.java ......

private List<String> incFriendReq;

public List<String> getFriendReq() {
    return incFriendReq;
}
Run Code Online (Sandbox Code Playgroud)

客户端

... Communication.java ......

public FriendRequestList getRequests() {
    sendObject(new GetRequests());
    return inputHandler.containsRequests();
}
Run Code Online (Sandbox Code Playgroud)

... MessageListener.java ...

public void run() {
    ...
    FriendRequestList requests = communication.getRequests();
    update(requestList, requests);
    // Here we have the problem. requests.size is never different from 0
}
Run Code Online (Sandbox Code Playgroud)

但是,如果我更新Worker.java这样做:

private Object getFriendRequests() {
    User me = Data.getUser(myUserName);
    if ( me == null ) {
        return new NoSuchUserException();
    }
    return new FriendList(me.getFriends().stream().collect(Collectors.toList()));
}
Run Code Online (Sandbox Code Playgroud)

其他用户请求我的友谊的瞬间,我在我的列表上看到了请求.是什么赋予了?这听起来像基础数据结构没有更新,竞争条件或其他东西.但修复方法是如何通过使用流来检索服务器端的数据.

请有人解释一下,在流式解决我的好奇问题之前,如何在Java 7中完成这项工作.

在笔记上

我想补充说,用户被放置在一个LinkedBlockingDeque并从Data对象中检索,这是工作者的共享资源.

小智 0

在我看来,incFriendReq直接返回列表getFriendReq是问题的根源之一。当您使用 java 8 并将该列表流式传输到新列表中时,您只是制作一个副本,因此没有有用的添加。如果是这种情况,您的服务器端代码也应该可以使用new ArrayList<>(me.getFriends()).

我将验证对该列表的所有访问是否已正确同步,并且您知道该列表何时何地发生变异。