关于JAVA的SOCKET多线程问题

newyu1127 2005-12-06 02:27:16
各位师兄好:
兄弟做好了一个网关。原理如下:网关程序需要去连接一堆的远程机子,并且是保持长连接,对每一个SOCKET进行相应的处理。远程机子的HOST和PORT都保存在一个ArrayList类型的集合中,我从中依次读取出每一个HOST和PORT,读出一个后,我先判断目前SOCKET连接组中是否有该SOCKET,如果没有则新建该SOCKET,同时启动一个线程来处理相应的事务。在这个线程中,当通讯出错(可能是SOCKET断掉了)出现异常时,将连接组中的该SOCKET删除。程序如下:
public class AmClient {
private ThreadGroup threadGroup; ///线程组
private Map socketGroup = new HashMap(); //SOCKET连接组
ArrayList ipArray;////HOST与PORT的集合
String host;
int port;
public AmClient() {
threadGroup = new ThreadGroup(AmClient.class.getName());
}
public static ArrayList readXml() {
........
//////这里给ipArray这个集合附值,写入N个HOST和PORT
}
public static void main(String[] args) {
AmClient amClient = new AmClient();
ipList = readXml();
while (true) {
try {
amClient.socketRequest(ipList);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void socketRequest(ArrayList ipArray) {
BufferedReader in;
PrintWriter out;
Socket socket;
for (Iterator it = ipArray.iterator(); it.hasNext(); ) {
Map ipMap = (Map) it.next(); ///一行是一个Map
////取出参数
host = (String) ipMap.get("host");
port = Integer.parseInt((String) ipMap.get("port"));
String key = host + Integer.toString(port);
try {
if (socketGroup.get(key) == null) {
/////当连接没有建立时或连接断开了,新建SOCKET后再启动线程
System.out.println("controller start...");
socket = new Socket(host, port);
AmConnection k = new AmConnection(socket, ipMap);
socketGroup.put(key, socket); ///放入连接组中
}

} catch (Exception e) {
////若出现断路情况,将socket从连接组中删除
if (socketGroup.get(key) != null) {
///若连接组中已有该连接
socketGroup.remove(key); ////从连接组中删除
}
System.out.println("socket断路了:" + e);
}
}
}
//处理每个SOCKET的线程
public class AmConnection extends Thread {
Socket client; //客户通信套接字
Map ipMap;
private String amHost,key;
private int amPort;
public AmConnection(Socket client, Map ipMap) {
super(threadGroup,
client.getLocalAddress() + Integer.toString(client.getPort()));
this.client = client;
this.ipMap = ipMap;
amHost = (String) ipMap.get("host");
amPort = Integer.parseInt((String) ipMap.get("port"));
key = amHost + Integer.toString(amPort);
start();
}
public void run() {
try {
........
////作相应的处理
} catch (Exception e) {
////若出现断路情况,将socket从连接组中删除
if (socketGroup.get(key) != null) {
///若连接组中已有该连接
socketGroup.remove(key); ////从连接组中删除
}
System.out.println("socket断路了:" + e);
interrupt(); //中断该线程
}
}

}
}
现在的问题是:我程序运行后,功能倒是可以实现,可是CPU的占用率达到了100%。后来我在main方法中加了一句
try {
amClient.socketRequest(ipList);
Thread.sleep(5000); //就加了这句
}
CPU就正常了。这是为什么呢?望知情者详细解释,谢谢。
...全文
3310 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
newyu1127 2005-12-20
  • 打赏
  • 举报
回复
自己再顶一天。
newyu1127 2005-12-19
  • 打赏
  • 举报
回复
自己再UP一下。
newyu1127 2005-12-14
  • 打赏
  • 举报
回复
NIO的socket有没有线程处理的例子。完整的一个例子,http://sunfruit.blogchina.com中的例子基本不能用啊。
xujiaqiang 2005-12-13
  • 打赏
  • 举报
回复
长连接可以
不要用线程
连接是资源,应按资源池的机制实现
管理几个连接池,每个连接池对应不同的远程机子
每个连接池有ip、port、初始连接数,最大连接数等参数
ResourcePoolManager负责参数读取、所有资源池初始化、销毁、关闭、重启、取空闲连接、返还连接等等
ResourcePool负责单个池的维护,ResourcePool中包含多个Resourceable实例
这样你可以管理监控每个池甚至每个连接的状态
dztc 2005-12-13
  • 打赏
  • 举报
回复
fdg
newyu1127 2005-12-13
  • 打赏
  • 举报
回复
TO cuij7718(沸腾的音乐 http://sunfruit.blogchina.com)
NIO的socket有没有线程处理的例子。
cuij7718 2005-12-10
  • 打赏
  • 举报
回复
对于NIO的socket的连接方式,我给你一个地址你看看吧,说的很好
http://www-128.ibm.com/developerworks/cn/java/j-javaio/
还有相关的信息,在网上搜搜吧
gemouzhi 2005-12-10
  • 打赏
  • 举报
回复
技术是需要转型之后再应用,痛苦的项目。^_^
newyu1127 2005-12-09
  • 打赏
  • 举报
回复
如果一定要使用socket 那么建议使用NIO的socket连接,可以实现非阻塞的连接,性能很好???
怎么用?能不能说的详细些???
treeroot 2005-12-09
  • 打赏
  • 举报
回复
up
cuij7718 2005-12-08
  • 打赏
  • 举报
回复
如果对于消息的安全要求不高,可以尝试UDP连接,这样不用保持长连接

还有,至于为什么CPU居高不下的原因 可能使你的线程里面的while里面没有sleep 导致的

如果一定要使用socket 那么建议使用NIO的socket连接,可以实现非阻塞的连接,性能很好
newyu1127 2005-12-08
  • 打赏
  • 举报
回复
嗯,第一个问题就象你说的,所谓的异常就是
远程计算机的当机 或 网络异常 或 硬件上的异常 或 人为结束掉进程
至于第二个问题:我的网关所放的位置很有可能是不固定的。如果是固定的,我曾经考虑过将网关即当客户端又当服务端,即一方面它向远程机子不停地发请求,一方面它开放一个端口来监听远程机子发过来的信息(并做相应处理)。这里需要远程的机子在收到请求后,不是直接将信息应答,而是用一个SOCKET去连接我的网关(我的IP和开放的端口),将信息传给网关。
这种方式已经被客户拒绝了,他们不允许这么做。所以我想我的网关位置固定与否就没多大关系了啦。
谢谢指教。另:师兄是否有QQ或MSN可以交流?
gemouzhi 2005-12-08
  • 打赏
  • 举报
回复
恩,看见你的短消息了,我加了你的MSN了。

你已经说出了我想说的(但竟然“这种方式已经被客户拒绝了,他们不允许这么做”)

我也知道你肯定也了解我这么问的意图。因为用那种方式主动转为被动,才能更好的管理和应用

技术。可是被客户拒绝了,我感觉很奇怪。(呵呵,说实话,这种方式被拒绝是很伤心的,

我想说的一些解决方案也是基于被客户拒绝的这种方式的)

这样的话,在MSN上只好讨论一下关于,单线程和多线程解耦了。

以前在JMS的回调时候我就想过你这种发散的servers问题,竟然还真有这样的应用。

(也许你远程上的程式并不是java写的)

anyway,MSN吧。我也是初学,希望能帮的上^_^.
gemouzhi 2005-12-07
  • 打赏
  • 举报
回复
恩,我了解你的意思,^_^我只有再问两个问题,才能给你全面的回复:

[1]关于检测, 按你的意思远程机子应该是长时间运行的, 你所谓的异常是什么?是不是

远程计算机的当机 或 网络异常 或 硬件上的异常 或 人为结束掉进程?

[2]你网关的IP是不是固定的?
newyu1127 2005-12-07
  • 打赏
  • 举报
回复
TO gemouzhi(gemouzhi)
谢谢你的回复,我把我网关的功能需求说明一下:
1、首先有多个远程机子。
2、网关这边要先发送一条请求信息去连接远程机子。远程机子收到请求信息后,将一条远程机子上的消息回送给网关。网关收到后,进行相应的处理后再发送请求信息给远程机子。如此循环,即网关发一条请求,远程才会回送一条消息。
3、若有发现连接断开的情况,将进行重连。
基本需求就是这样,我也不想保持长连接,可是如果不保持的话,那么如何保证与每个远程机子的实时通讯?难道每次都要new Socket一下,处理一条消息后就close掉。连接建立起来后,双方的通讯频率是很高的,这也是客户要求保持长连接的原因。
所以我的程序就是考虑把存放远程HOST和PORT的ipArray遍历一下,每取出一条HOST和PORT,就查一下是否有在连接组socketGroup中有该SOCKET了,如果没有,就 new Socket(host, port),同时启用一个线程来处理这个SOCKET的实时通讯的事务。如果连接组中已存在这个SOCKET,那就不管了,因为这个SOCKET的线程已经在启动运行了。
程序在第一次运行的时候,肯定所有的SOCKET都要新建的。然后,只有在这个SOCKET的通讯出现错误了(基本上就是SOCKET异常断开了),才会新建连接的。
至于主方法中
while (true) {
try {
amClient.socketRequest(ipList);
Thread.sleep(5000);
} catch (Exception e) {
e.printStackTrace();
}}
amClient.socketRequest(ipList);这句我也觉得放在while (true)怪怪的,正如你说的不应该去阁5秒钟,就去问每一个小朋友。可是我不放在while (true)里,那么程序一运行起来后,CPU就占用到100%,而且放在while里面的还有一个好处就是,当发现SOCKET断开后,每隔5秒会一次重连的尝试,否则就会一直进行重连操作至到连接成功为止,这样比较占资源吧。
望师兄指教,谢谢。
gemouzhi 2005-12-06
  • 打赏
  • 举报
回复
soory, 刚才给别人化妆去了, 没及时回你的帖子.

1,你的动机必须再和我说一下, 就是主动方与被动方? 还有业务逻辑的处理所需要的时间?

2,照顾一群小朋友, 不应该去阁5秒钟,就去问每一个小朋友,谁要上厕所?

哪个小朋友要上厕所就举手好了, 所以小朋友是主动方.

3,为什么要保持长连接? 这显然是不好的.要不就不用出现JMS的topic了.

4,你把你的需求抽象一下, 贴出来, 也许我能帮你, 我也是初学, 水平有限, 希望不会误导你.
newyu1127 2005-12-06
  • 打赏
  • 举报
回复
TO 回复人: lyzkkzong(苯苯)
谢谢回复
TO 回复人: cuij7718(沸腾的音乐 http://sunfruit.blogchina.com) ( )
那应该如何理解多线程呢?象这样的情况,同时要连接多个远程端,而且又必须保证每个SOCKET的实时通讯。不用线程来处理,怎么做才能保持每个SOCKET的长连接???
TO 回复人: gemouzhi(gemouzhi)
那正确的方向是什么,请详细说明,谢谢。
cuij7718 2005-12-06
  • 打赏
  • 举报
回复
感觉搂主没有理解多线程的意思
gemouzhi 2005-12-06
  • 打赏
  • 举报
回复
哈哈,你走错方向了。
lyzkkzong 2005-12-06
  • 打赏
  • 举报
回复
Thread.sleep(5000)让线程不一直占用CPU,这样CPU自然就下来。

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧