我正在编写一个用Java编写的聊天程序,并使用一个Thread,一个客户端和几个可以联机并断开连接的客户端。 每个新用户都可以看到并与每个人交谈,每个人都能看到他。 现在,我搜索了一种在那里进行多次交流的方法。类似的东西:第一个和第二个在私人房间,第三个和第四个在私人房间.... 我想用ThreadGroup这样做,但由于某种原因,我找不到一个可以解释我的文件,如果这是相关的或不... 无论如何,这是正确的方式吗? 我该怎么做呢?
答案 0 :(得分:2)
如果我理解你的应用程序,我不确定你需要线程(除非这是一个要求)。
只需让每个用户注册到一个房间 - 这可以是一个简单的Map
,其中房间作为键,用户列表作为值。一旦您需要将消息发送到房间,只需获取该房间中的整个用户列表(折扣发送用户)并将消息发送给每个用户。
如果你想使用线程,你需要一个稍微复杂的模型,就像每个房间的经理线程一样,这可以通过简单的线程池和ExecutorService
轻松完成,就像这样:
ExecutorService es = Executors.newFixedThreadPool(3); // or whatever
for (Runnable r : someRunnableList)
{
es.execute(r);
}
(我强烈建议如果你在你的应用程序中使用并发,请小心确保你没有引入任何错误。修复并发错误并不是一个令人愉快的考验。)
答案 1 :(得分:0)
虽然不是你问的问题的答案,如果我是你,我不会从这里开始。除非您有选择线程的特定原因,并且您对使用Java进行多线程编程感到满意,否则您可能会考虑使用非阻塞IO和单线程模型的方法。 java.nio包(自Java 1.4以来引入)提供了执行此操作的基础。
您还可以考虑实施解决方案的众多经过强化战斗的框架之一,例如Grizzly或Mina。使用框架的优势在于,您可以在活跃社区和经过验证的解决方案的支持下构建单个或安全的多线程IO应用程序(这可能是一项非常重要的工作)。
答案 2 :(得分:0)
线程可能不是解决此问题的最佳解决方案。您可能会发现线程引入了一些新问题,这些问题只会让您无法使应用程序正常运行。
正如你所描述的那样,可能有用的是用一个类的实例代表每个用户,称之为ChatUser(目前缺少一个更好的术语),并嵌入允许谁的逻辑与谁谈谈ChatUser的方法。例如,每个实例都有一个属性,说明用户所在的房间,当用户想要说某些内容时,处理该方法的方法会检查ChatUser的其他实例,并仅将字符串发送给具有匹配项的字符串。房间属性。
答案 3 :(得分:0)
我想虽然你可以只使用一个线程实现它,但它肯定会很麻烦,因为所有请求都将按顺序处理,并且当涉及网络时,它具有相当大的延迟并且容易出现超时,你的app等问题。很容易变得非常反应迟钝。假设有人与互联网断开连接。如果你只有一个线程,你的整个应用程序将会一直保持到超时,你发现这个客户端出了问题!即使某人决定安静一段时间,你也会遇到麻烦(它可能很容易解决,但仍然更加复杂)。
因此,尽管不是中心,但非常推荐使用多线程。
但是,并发专家组不鼓励使用ThreadGroup
,因此您可能不应该使用它。
我不清楚你当前应用的设计是什么。如果您能告诉我们更多信息,我们可能会为您提供更多帮助。
一种简单的方法是使用HTTP服务器和客户端的组合。因此每个客户端也是一个服务器,并在连接时将其回调地址(用于其服务器)传递给中央服务器。随后,客户端将通过HTTP POST将新消息推送到中央服务器,中央服务器将通过HTTP POST将这些消息推送到客户端。
如果您选择了这样的设计,则线程是不可避免的。将发出HTTP POST请求的线程可以是单线程的(每个JVM),但是接收HTTP请求的线程不能是同一个线程(这不是不可能,但我认为这不可行)。
所以最简单的方法是嵌入令牌以识别该群组,并使用此类似的(仅用于非常基本的插图!):
class Chat {
private final ConcurrentMap<String,Set<URI>> rooms;
{
rooms = new ConcurrentHashMap<String,Set<URI>>();
}
public void connect(String roomKey, URI callbackAddr){
Set<URI> users = rooms.get(roomKey);
if(users==null){
rooms.putIfAbsent(roomKey,new ConcurrentSkipListSet<URI>());
}
users = rooms.get(roomKey);
users.add(callbackAddr);
}
public void say(String roomKey, String message){
if(rooms.get(roomKey)==null){
throw new RuntimeException("Room " + roomKey + " does not exist.");
}
for(URI dest : rooms.get(roomKey)){
HTTPPoster.postMessage(dest, roomKey, message);
}
}
}
您的客户端会有类似的内容。