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

}
时间: 2024-10-05 20:01:35

java多线程检测可用IP的相关文章

java 检测代理IP是否准确

我这里提供2个方法都可以实现:第一个是createIPAddress()和convertStreamToString() import java.io.IOException; import java.io.InputStream; import java.net.InetSocketAddress; import java.net.Proxy; import java.net.URL; import java.net.URLConnection; import java.nio.charset

从JAVA多线程理解到集群分布式和网络设计的浅析

对于JAVA多线程的应用非常广泛,现在的系统没有多线程几乎什么也做不了,很多时候我们在何种场合如何应用多线程成为一种首先需要选择的问题,另外关于java多线程的知识也是非常的多,本文中先介绍和说明一些常用的,在后续文章中如果有必要再说明更加复杂的吧,本文主要说明多线程的一下几个内容: 1.在应用开发中什么时候选择多线程? 2.多线程应该注意些什么? 3.状态转换控制,如何解决死锁? 4.如何设计一个具有可扩展性的多线程处理器? 5.多线程联想:在多主机下的扩展-集群? 6.WEB应用的多线程以及

java多线程常见面试题

下面是Java线程相关的热门面试题,你可以用它来好好准备面试. 1) 什么是线程? 线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位.程序员可以通过它进行多处理器编程,你可以使用多线程对运算密集型任务提速.比如,如果一个线程完成一个任务要100毫秒,那么用十个线程完成改任务只需10毫秒.J 2) 线程和进程有什么区别? 线程是进程的子集,一个进程可以有很多线程,每条线程并行执行不同的任务.不同的进程使用不同的内存空间,而所有的线程共享一片相同的内存空间.别把它

50个Java多线程面试题

不管你是新程序员还是老手,你一定在面试中遇到过有关线程的问题.Java 语言一个重要的特点就是内置了对并发的支持,让 Java 大受企业和程序员的欢迎.大多数待遇丰厚的 Java 开发职位都要求开发者精通多线程技术并且有丰富的 Java 程序开发.调试.优化经验,所以线程相关的问题在面试中经常会被提到. 在典型的 Java 面试中, 面试官会从线程的基本概念问起, 如:为什么你需要使用线程, 如何创建线程,用什么方式创建线程比较好(比如:继承 thread 类还是调用 Runnable 接口),

Java之十三 Java多线程

你一定知道多任务处理,因为它实际上被所有的现代操作系统所支持.然而,多任务处理有两种截然不同的类型:基于进程的和基于线程的.认识两者的不同是十分重要的.对很多读者,基于进程的多任务处理是更熟悉的形式.进程(process)本质上是一个执行的程序.因此,基于进程(process-based)的多任务处理的特点是允许你的计算机同时运行两个或更多的程序.举例来说,基于进程的多任务处理使你在运用文本编辑器的时候可以同时运行Java编译器.在基于进程的多任务处理中,程序是调度程序所分派的最小代码单位.在基

Java多线程知识小抄集(三)

本文主要整理博主遇到的Java多线程的相关知识点,适合速记,故命名为"小抄集".本文没有特别重点,每一项针对一个多线程知识做一个概要性总结,也有一些会带一点例子,习题方便理解和记忆. 51. SimpleDateFormat非线程安全 当多个线程共享一个SimpleDateFormat实例的时候,就会出现难以预料的异常. 主要原因是parse()方法使用calendar来生成返回的Date实例,而每次parse之前,都会把calendar里的相关属性清除掉.问题是这个calendar是

Java多线程面试题整理

线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位.程序员可以通过它进行多处理器编程,你可以使用多线程对运算密集型任务提速.比如,如果一个线程完成一个任务要100毫秒,那么用十个线程完成改任务只需10毫秒.Java在语言层面对多线程提供了卓越的支持,它也是一个很好的卖点. 2) 线程和进程有什么区别? 线程是进程的子集,一个进程可以有很多线程,每条线程并行执行不同的任务.不同的进程使用不同的内存空间,而所有的线程共享一片相同的内存空间.别把它和栈内存搞混,每个线

java多线程面试题整理及答案(2018年)

java多线程面试题整理及答案(2018年) 什么是线程? 线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位.程序员可以通过它进行多处理器编程,你可以使用多线程对 运算密集型任务提速.比如,如果一个线程完成一个任务要100毫秒,那么用十个线程完成改任务只需10毫秒.Java在语言层面对多线程提供了卓越的支 持,它也是一个很好的卖点. 线程和进程有什么区别? 线程是进程的子集,一个进程可以有很多线程,每条线程并行执行不同的任务.不同的进程使用不同的内存空间,而所

Java多线程:Linux多路复用,Java NIO与Netty简述

JVM的多路复用器实现原理 Linux 2.5以前:select/poll Linux 2.6以后: epoll Windows: IOCP Free BSD, OS X: kqueue 下面仅讲解Linux的多路复用. Linux中的IO Linux的IO将所有外部设备都看作文件来操作,与外部设备的操作都可以看做文件操作,其读写都使用内核提供的系统调用,内核会返回一个文件描述符(fd, file descriptor),例如socket读写使用socketfd.描述符是一个索引,指向内核中一个