我试图在Java中实现一个多线程服务器,服务器为每个连接到它的客户机生成一个新线程。通信在一个类中执行,该类实现可运行接口,并将套接字描述符作为输入。当一个新客户端连接时,我会生成一个带有套接字描述符编号的新线程。
我需要在服务器上维护两个ArrayList,每当新客户端加入系统时都会更新(带有客户端发送的一些数据)。如何在运行在不同线程中的多个客户端之间完成这种共享ArrayList的行为?
如果您希望ArrayList
s存储每个客户端的信息并通过客户端ID访问它,我建议您只使用java.util.concurrent.ContoptHashMap
,并将客户端ID作为键,因为这是非常简单的实现。
如果你真的需要一个ArrayList
,我会把它作为实现细节隐藏在服务器代码中。然后从Runnable
s调用一些服务器方法来更新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中的锁定速度非常快,所以在很多情况下,这个简单的解决方案可能已经足够好了。
如果您希望有很多客户机,并且希望随机访问它们,请使用ConcurrentSkipListMap。这将为您提供一个高效、线程安全、无阻塞的映射。使用索引号作为键,或者使用更有意义的内容。如果你只需要一个简单的列表(没有随机访问),那么就使用ConcurrentLinkedQueue,这与ConcurrentLinkedQueue基本相同,只是它是一个单独链接的列表,而不是映射。
另一种方法是使用ArrayList(或数组),但将其视为不可变的。当您需要添加客户端时,复制旧客户端,将客户端添加到其中,然后将新客户端替换为旧客户端。(根据erickson的建议,CopyOnWriteArrayList可以为您完成此操作。)这将在维护列表时花费您的成本,但可以让大量线程同时掌握和使用列表。诚然,只有在您需要在每次添加后处理列表、可能对其进行排序以及添加和删除受添加影响的一些条目时,这种技术才会变得真正有用。)
您可以在主服务器线程中创建一个并发集合的实例,然后通过构造函数将其传递给您的每个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