【问题标题】:ArrayList concurrency across socket connections跨套接字连接的 ArrayList 并发
【发布时间】:2015-10-28 05:12:54
【问题描述】:

我有一个问题。我认为这与线程的并发或同步有关,尽管我无法确定正在发生的事情。

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

我们从客户端向另一个用户(工作人员)发送好友请求。 所以我们发送请求并将我们自己的用户名添加到他们的User.incFriendReq-list。该实例是一个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());
}

...用户.java ...

private List<String> incFriendReq;

public List<String> getFriendReq() {
    return incFriendReq;
}

客户端

... Communication.java ...

public FriendRequestList getRequests() {
    sendObject(new GetRequests());
    return inputHandler.containsRequests();
}

... MessageListener.java ...

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

但是,如果我更新 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()));
}

当其他用户请求我的友谊时,我会在我的列表中看到该请求。 是什么赋予了?在我看来,这听起来像是底层数据结构没有更新,竞争条件或其他东西。 但解决方法是我如何使用流在服务器端检索数据。

请有人解释一下,以及如何在 Java 7 中完成此操作,然后流将解决我对我来说好奇的问题。

在笔记上

我想补充一点,用户被放置在 LinkedBlockingDeque 中,并从 Data 对象中检索,这是工作人员的共享资源。

【问题讨论】:

    标签: java multithreading sockets arraylist


    【解决方案1】:

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

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

    【讨论】:

    • 这段代码的迷人之处在于,在调试我从getFriendReq 获得的列表时,实际上大小为1。但是当我收到另一边的对象时,它的大小为零。
    • 在我看来,您的列表在服务器端的状态没有得到适当的维护。该列表的大小可能为零,因为该列表的陈旧副本仍在某个地方要返回,但与您正在查看的值不同(检查调试器中的对象 ID 以进行验证)或存在并发与内存可见性相关的问题,即未跨线程公开变异数据(确保对列表的所有访问都在同一个锁上同步)。
    猜你喜欢
    • 2011-12-30
    • 1970-01-01
    • 2020-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多