java多线程检测可用IP
最近做系统性能优化的时候遇到的一个问题,解决之后分享给大家。
我们通过socket建立连接的时候,如果我们计算机不能与指定的站点连接上,那么这将会导致系统卡在socket的connect这个方法上,
我们都知道socket建立连接需要三次握手,计算机向服务器发送消息头,服务器返回,这时候socket基本连接成功,但是如果连接
不上的话这里会卡一个Timeout的时间,时间一到,方法返回失败,socket默认的timeout好像是20秒,
我们系统现在有一个从可用的ip列表里面检测出一个可用的ip,拿出来作为可用数据保存到内存。
之前我们是串行测试,一个不可用再去尝试下一个,这个操作将业务流程停止在这一步很长时间。
现在改成并行测试,开启多个线程测试,有可用的ip之后直接返回,这个检测操作的时间缩减到毫秒级,大大提升了系统性能。
具体代码如下:
资源接口:
package com.sunyard.frame.resource.base; /** * 可初始化的资源 * * @author zhangWei * @since 2014年10月29日 下午6:58:55 * @version zhw_1.1 */ public abstract class InitAble { /** * 初始化 * @return true 初始化成功 */ public abstract boolean init(); /** * 销毁该资源,如关闭连接等 */ public abstract void destory(); }
package com.sunyard.frame.resource; import java.util.List; import com.sunyard.frame.resource.base.InitAble; import com.sunyard.frame.thread.ThreadPool; import com.sunyard.frame.utils.ListUtils; /** * 资源探测器,从一组资源中检测出一个可用的资源 * * @author zhangWei * @since 2014年10月29日 下午7:00:45 * @version zhw_1.1 */ public class ResourceDetector { /**待检测的资源*/ private List<? extends InitAble> resources; /**创建该对象的线程*/ private Thread mainThread; /**探测结果*/ private InitAble result; /**用于并发探测可用资源的线程池,可以用java的ExecutorService代替*/ private ThreadPool pool = new ThreadPool(10); /**探测失败的记录数*/ private Integer failCount = 0; public ResourceDetector(List<? extends InitAble> resources) { super(); this.resources = resources; this.mainThread = Thread.currentThread(); } /** * 探测器开始探测可用的资源 * * @author zhangWei * @since 2014年10月29日 下午7:20:21 */ public InitAble detect(){ if(ListUtils.isNotEmpty(resources)){ for(InitAble i:resources){ pool.execute(createDetectTask(i)); } synchronized (mainThread) { try { mainThread.wait(); } catch (InterruptedException e) { } } return result; } else { return null; } } /**创建探测一个资源的子线程*/ private Runnable createDetectTask(final InitAble i){ return new Runnable() { @Override public void run() { try{ if(i.init()){ result = i; synchronized (mainThread) { mainThread.notify(); } } else { synchronized (failCount) { if(++failCount == resources.size()){ synchronized (mainThread) { mainThread.notify(); } } } } } finally { i.destory(); } } }; } }
测试类:
这里的 SocketDecorate是 InitAble的子类,ServerSocketProxy是启动一个服务端监听,大家可以自行实现,代码太多就不复制上去了
package test.resource; import java.io.IOException; import java.util.ArrayList; import java.util.List; import test.socket.ServerServiceImpl; import junit.framework.TestCase; import com.sunyard.frame.resource.ResourceDetector; import com.sunyard.frame.socket.client.SocketDecorate; import com.sunyard.frame.socket.server.ServerSocketProxy; public class TestResource extends TestCase { public void testDetect(){ //创建一个ServerSocket ServerSocketProxy ss; try { ss = new ServerSocketProxy(1000, ServerServiceImpl.class, true); ss.startServer(); } catch (IOException e) { } SocketDecorate d1 = new SocketDecorate("168.1.1.1", 1000); SocketDecorate d2 = new SocketDecorate("168.1.1.2", 1000); SocketDecorate d3 = new SocketDecorate("168.1.1.3", 1000); SocketDecorate d4 = new SocketDecorate("168.1.1.4", 1000); SocketDecorate d5 = new SocketDecorate("168.1.1.5", 1000); SocketDecorate d6 = new SocketDecorate("168.1.1.6", 1000); SocketDecorate d7 = new SocketDecorate("168.1.1.7", 1000); SocketDecorate d8 = new SocketDecorate("127.0.0.1", 1000); List<SocketDecorate> resources = new ArrayList<SocketDecorate>(); resources.add(d1); resources.add(d2); resources.add(d3); resources.add(d4); resources.add(d5); resources.add(d6); resources.add(d7); resources.add(d8); ResourceDetector detector = new ResourceDetector(resources); SocketDecorate s = (SocketDecorate) detector.detect(); System.out.println(s); } }
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。