[置頂] java多線程檢測可用IP
來源:程序員人生 發布時間:2014-11-12 08:52:45 閱讀次數:2075次
最近做系統性能優化的時候遇到的1個問題,解決以后分享給大家。
我們通過socket建立連接的時候,如果我們計算機不能與指定的站點連接上,那末這將會致使系統卡在socket的connect這個方法上,
我們都知道socket建立連接需要3次握手,計算機向http://www.jyygyx.com/server/發送消息頭,http://www.jyygyx.com/server/返回,這時候候socket基本連接成功,但是如果連接
不上的話這里會卡1個Timeout的時間,時間1到,方法返回失敗,socket默許的timeout好像是20秒,
我們系統現在有1個從可用的ip列表里面檢測出1個可用的ip,拿出來作為可用數據保存到內存。
之前我們是串行測試,1個不可用再去嘗試下1個,這個操作將業務流程停止在這1步很長時間。
現在改成并行測試,開啟多個線程測試,有可用的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;
/**
* 資源探測器,從1組資源中檢測出1個可用的資源
*
* @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;
}
}
/**創建探測1個資源的子線程*/
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是啟動1個服務端監聽,大家可以自行實現,代碼太多就不復制上去了
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(){
//創建1個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);
}
}
生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈