zoukankan      html  css  js  c++  java
  • java多线程检测可用IP

    最近有一个问题进行系统性能优化的时候来到。解析分享给大家后,。

    我们socket当建立连接,假设我们不能将计算机连接到指定的站点,那么这将导致系统卡socket的connect在此方法。

    我们都知道socket它需要三次握手建立连接。计算机server发送消息头,server返回。这时候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);
    	}
    
    }
    



    版权声明:本文博主原创文章,博客,未经同意不得转载。

  • 相关阅读:
    用脚本保存prefab
    如何在Unity 3D中掷骰子
    转发收藏【原创】浅谈UGUI的ETC1+A的纹理压缩方案总结
    Unity鼠标拖拽控制人物的左右旋转
    蛋哥的学习笔记之-基于Unity的Shader编程:X-1 音乐水波特效
    xlua中hotfix简单实用
    tolua调用C#中的静态类
    scut和unity之间收发请求返回
    scut服务器unity配置
    HTTP网络请求
  • 原文地址:https://www.cnblogs.com/zfyouxi/p/4806711.html
Copyright © 2011-2022 走看看