当前位置: 首页 > 知识库问答 >
问题:

多线程服务器共享ArrayList

荆乐
2023-03-14

我试图在Java中实现一个多线程服务器,服务器为每个连接到它的客户机生成一个新线程。通信在一个类中执行,该类实现可运行接口,并将套接字描述符作为输入。当一个新客户端连接时,我会生成一个带有套接字描述符编号的新线程。

我需要在服务器上维护两个ArrayList,每当新客户端加入系统时都会更新(带有客户端发送的一些数据)。如何在运行在不同线程中的多个客户端之间完成这种共享ArrayList的行为?

共有3个答案

牧信厚
2023-03-14

如果您希望ArrayLists存储每个客户端的信息并通过客户端ID访问它,我建议您只使用java.util.concurrent.ContoptHashMap,并将客户端ID作为键,因为这是非常简单的实现。

如果你真的需要一个ArrayList,我会把它作为实现细节隐藏在服务器代码中。然后从Runnables调用一些服务器方法来更新ArrayList。通过这种方式,你可以从非常简单的事情开始,比如:

public class Server {
    ...      
    private ArrayList<Info> infos = new ArrayList<Info>();
    ...
    // Create one method for each *abstract* operation
    // that you need to perform on the ArrayList
    // (Do *NOT* implement read / write primitives
    // unless that is exactly what you need. The idea is
    // that all synchronization that you might need on 
    // the ArrayList happens inside those methods, so
    // the Runnables are unaware of the implementation
    // you haven chosen.)

    // Here I have used example operations that are
    // a bit more complex than read / write primitives
    // so the intention is more clear.

    public void clearInfo(int pos) {
        synchronized (infos) {
            infos.set(pos, null);
        }
    }

    public Info updateInfo(int pos, Info info) {
        Info oldInfo = null;
        synchronized (infos) {
            oldInfo = infos.get(pos);
            infos.set(pos, info);
        }
        return oldInfo;
    }
    ...
    public Info readInfo(int pos) {
        Info info = null;
        synchronized (infos) {
            infos.get(pos);
            info.incrementReadCount();
        }
        return null;
    }
    ...
}
...
public class ClientRunnable implements Runnable {
    ...
    private Server server;
    ...
    @Override
    public void run() {
        ...
        Info info = // getInfo();
        int writePos = // getWritePos();
        Info old = server.updateInfo(writePos, info);
        ...
        int readPos = // getReadPos();            
        Info newInfo = server.readInfo(readPos);
        ...
    }
    ...
}

然后,在分析应用程序时,如果在访问列表时发现争用,可以微调锁定,甚至将实现更改为无锁实现,同时将代码中的影响降至最低。现在Java中的锁定速度非常快,所以在很多情况下,这个简单的解决方案可能已经足够好了。

吴炎彬
2023-03-14

如果您希望有很多客户机,并且希望随机访问它们,请使用ConcurrentSkipListMap。这将为您提供一个高效、线程安全、无阻塞的映射。使用索引号作为键,或者使用更有意义的内容。如果你只需要一个简单的列表(没有随机访问),那么就使用ConcurrentLinkedQueue,这与ConcurrentLinkedQueue基本相同,只是它是一个单独链接的列表,而不是映射。

另一种方法是使用ArrayList(或数组),但将其视为不可变的。当您需要添加客户端时,复制旧客户端,将客户端添加到其中,然后将新客户端替换为旧客户端。(根据erickson的建议,CopyOnWriteArrayList可以为您完成此操作。)这将在维护列表时花费您的成本,但可以让大量线程同时掌握和使用列表。诚然,只有在您需要在每次添加后处理列表、可能对其进行排序以及添加和删除受添加影响的一些条目时,这种技术才会变得真正有用。)

郎吉星
2023-03-14

您可以在主服务器线程中创建一个并发集合的实例,然后通过构造函数将其传递给您的每个Runnable套接字处理程序。(听起来您已经在做这样的事情来传递Socket本身。)

CopyOnWriteArrayList是一个并发List实现,但它不是特别高效。还有其他支持并发访问的集合类型,可能会提供更好的性能。

 类似资料:
  • 本文向大家介绍Springboot实现多服务器session共享,包括了Springboot实现多服务器session共享的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了springboot实现多服务器session共享的具体代码,供大家参考,具体内容如下 环境: springboot:2.0.4 redis:3.2.100 jdk:1.8 eclipse:4.9.0 1.原理 正常

  • 使用ws,Node.js WebSocket库,可以让多个服务器共享一个HTTP/S服务器。 有可能用socket.io做同样的事情吗?

  • 我是个新手,如果你能给我建议的话,请告诉我。我有一个向客户端广播消息的服务器。然后客户端将回复发送回服务器。我想用单独的线程处理每个回复。每个回复都有mesage id和thread id。我如何用来自所有线程的信息填充一些结构,然后读取它 也从我的代码,它是正确地创建线程,而还是它存在某种方式来创建线程,只是如果我得到客户端的回复? 我是从正确的理解开始的吗? 非常感谢。

  • 服务器 用于监听服务器中每个客户机的线程在名为OyenteCliente(ClientListener)的类中实现,每个客户机中监听服务器petitios的线程在OyenteServidor(ServerListener)中实现。 客户监听器 非常感谢!

  • 我有两个线程,一个在一个套接字上监听并添加到队列中,另一个从队列中减去并提交处理。第二个线程在队列为空时Hibernate。这个睡眠不知怎么会影响第一个线程,也就是说,如果您移除睡眠或使它变大,那么第一个线程的socket.receive中的延迟就会增加。如果我保持尽可能低的睡眠,它会变得更好,但不是完美的。我做错了什么?

  • 问题内容: 首先,我想说两件事。首先,很抱歉,如果已经有人问过这个问题,我已经搜索了与此主题相关的类似问题,但找不到解决方案。其次,对于冗长的问题,我们深表歉意,如有任何错误,请通知我,我将确保做出适当的更改:)。 我是Android开发的新手(大约2个月),所以请原谅我的无知。我有关于Android服务的问题。 我的问题如下,我创建了以下3个应用程序: 一个包含小型测试服务( myService