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);
	}

}



郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。