深入理解Java之线程池- http://blog.csdn.net/qq_35101189/article/details/60745796?ref=myread
Android Handler+ExecutorService(线程池)+MessageQueue模式+缓存模式--http://www.eoeandroid.com/thread-210082-1-1.html
java自带线程池和队列详细讲解,android中适用- https://my.oschina.net/u/1424386/blog/336087 ,
java自带线程池和队列详细讲解- http://blog.csdn.net/sd0902/article/details/8395677
-- Java中线程池,你真的会用吗- https://blog.csdn.net/hollis_chuang/article/details/83743723
线程池底层确实是通过LinkedBlockingQueue实现的。创建的最大线程数可能是Integer.MAX_VALUE,而创建这么多线
程,必然就有可能导致OOM。
推荐使用guava提供的ThreadFactoryBuilder来创建线程池。
public class ExecutorsDemo {
private static ThreadFactory namedThreadFactory = new ThreadFactoryBuilder() .setNameFormat("demo-pool-%d").build();
private static ExecutorService pool = new ThreadPoolExecutor(5, 200, 0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue
public static void main(String[] args) {
for (int i = 0; i < Integer.MAX_VALUE; i++) {
pool.execute(new SubThread());
}
}
}
- 线程池执行流程:
> 停止线程thread,(线程池)
线程对象属于一次性消耗品,一般线程执行完run方法之后,线程就正常结束了,线程结束之后就报废了,不能再次start,只能新建一个线程对象。但有时run方法是永远不会结束的。例如在程序中使用线程进行Socket监听请求,或是其他的需要循环处理的任务。在这种情况下,一般是将这些任务放在一个循环中,如while循环。当需要结束线程时,如何退出线程呢?
如何终止java线程- http://blog.csdn.net/anhuidelinger/article/details/11746365
* 在Java5的java.util.concurrent中得到了回答:使用interrupt(),让线程在run方法中停止,但还得设置个标志。不要去使用stop(),产生了不完整的残废数据。
-- Android java 中如何优雅的结束线程
如何正确地停止一个线程?-- http://www.cnblogs.com/greta/p/5624839.html
有三种方法可以结束线程:
1. 使用violate boolean变量退出标志,使线程正常退出,也就是当run方法完成后线程终止;
2. 使用interrupt()方法中断线程,因为线程有可能在wait()或sleep(), 提高停止线程的即时性;
3. 使用stop方法强行终止线程(不推荐使用,可能发生不可预料的结果);
4. 对于blocking IO的处理,尽量使用InterruptibleChannel来代替blocking IO;
前两种方法都可以实现线程的正常退出,也就是要谈的优雅结束线程;第3种方法相当于电脑断电关机一样,是不安全的方法。
1)使用退出标志终止线程
使用一个变量来控制循环,例如最直接的方法就是设一个boolean类型的标志,并通过设置这个标志为true或false来控制while循环是否退出。代码如下:
public class ThreadSafe extends Thread {
public volatile boolean exit = false;
public void run() {
while (!exit){
//do something
}
}
}
定义了一个退出标志exit,当exit为true时,while循环退出,exit的默认值为false.在定义exit时,使用了一个Java关键字volatile,这个关键字的目的是使exit同步,也就是说在同一时刻只能由一个线程来修改exit的值,
2)使用interrupt()方法终止线程
使用interrupt()方法来终端线程可分为两种情况:
线程处于阻塞状态,如使用了sleep,同步锁的wait,socket的receiver,accept等方法时,会使线程处于阻塞状态。当调用线程的interrupt()方法时,系统会抛出一个InterruptedException异常,代码中通过捕获异常,然后break跳出循环状态,使线程正常结束。通常很多人认为只要调用interrupt方法线程就会结束,实际上是错的,一定要先捕获InterruptedException异常之后通过break来跳出循环,才能正常结束run方法。
public class ThreadSafe extends Thread {
public void run() {
while (true){
try{
Thread.sleep(5*1000);阻塞5妙
}catch(InterruptedException e){
e.printStackTrace();
break;//捕获到异常之后,执行break跳出循环。
}
}
}
}
线程未进入阻塞状态,使用isInterrupted()判断线程的中断标志来退出循环,当使用interrupt()方法时,中断标志就会置true,和使用自定义的标志来控制循环是一样的道理。
public class ThreadSafe extends Thread {
public void run() {
while (!isInterrupted()){
//do something, but no tthrow InterruptedException
}
}
}
为什么要区分进入阻塞状态和和非阻塞状态两种情况了,是因为当阻塞状态时,如果有interrupt()发生,系统除了会抛出InterruptedException异常外,还会调用interrupted()函数,调用时能获取到中断状态是true的状态,调用完之后会复位中断状态为false,所以异常抛出之后通过isInterrupted()是获取不到中断状态是true的状态,从而不能退出循环,因此在线程未进入阻塞的代码段时是可以通过isInterrupted()来判断中断是否发生来控制循环,在进入阻塞状态后要通过捕获异常来退出循环。因此使用interrupt()来退出线程的最好的方式应该是两种情况都要考虑:
public class ThreadSafe extends Thread {
public void run() {
while (!isInterrupted()){ //非阻塞过程中通过判断中断标志来退出
try{
Thread.sleep(5*1000);//阻塞过程捕获中断异常来退出
}catch(InterruptedException e){
e.printStackTrace();
break;//捕获到异常之后,执行break跳出循环。
}
}
}
}
3)使用stop方法终止线程
程序中可以直接使用thread.stop()来强行终止线程,但是stop方法是很危险的,就象突然关闭计算机电源,而不是按正常程序关机一样,可能会产生不可预料的结果,不安全主要是:thread.stop()调用之后,创建子线程的线程就会抛出ThreadDeatherror的错误,并且会释放子线程所持有的所有锁。一般任何进行加锁的代码块,都是为了保护数据的一致性,如果在调用thread.stop()后导致了该线程所持有的所有锁的突然释放(不可控制),那么被保护数据就有可能呈现不一致性,其他线程在使用这些被破坏的数据时,有可能导致一些很奇怪的应用程序错误。因此,并不推荐使用stop方法来终止线程。
> 安全的关闭线程池或线程
Java关闭线程的安全方法- http://www.cnblogs.com/simbachen/p/4009562.html
线程池动态并安全地中断所有线程- http://blog.csdn.net/a1053904672/article/details/72170289
java多线程]如何安全的退出线程- http://blog.csdn.net/Zzrdark_/article/details/78291073
Java四种线程池的使用:http://blog.csdn.net/u013216593/article/details/42426289
四种线程池:newCacheThreadPool newFixedThreadPool newScheduledThreadPool newSingleThreadExecutor
Android性能优化之使用线程池处理异步任务-- http://blog.csdn.net/u010687392/article/details/49850803
-- 线程池的关闭
1.shutDown() 关闭线程池,不影响已经提交的任务
2.shutDownNow() 关闭线程池,并尝试去终止正在执行的线程
3.allowCoreThreadTimeOut(boolean value) 允许核心线程闲置超时时被回收
4.submit 一般情况下我们使用execute来提交任务,但是有时候可能也会用到submit,使用submit的好处是submit有返回值
> 线程池
-- 在什么情况下使用线程池?
1.单个任务处理的时间比较短
2.将需处理的任务的数量大
-- 使用线程池的好处:
1.提升性能。减少在创建和销毁线程上所花的时间以及系统资源的CPU开销
2.如不使用线程池,有可能造成系统创建大量线程而导致消耗完系统内存以及”过度切换”。
3.防止内存过度消耗。控制活动线程的数量,防止并发线程过多。在Android中当同时并发多个网络线程时,引入线程池技术会极大地提高APP的性能。开
启的thread越多意味着你的app内存消耗越多,速度也就越来越慢。
-- Java/Android线程池框架的结构主要包括3个部分:
1.任务:包括被执行任务需要实现的接口类:Runnable 或 Callable
2.任务的执行器:包括任务执行机制的核心接口类Executor,以及继承自Executor的EexcutorService接口。
3.执行器的创建者,工厂类Executors
-- 一个线程池包括以下四个基本组成部分:
1、线程池管理器(ThreadPool):用于创建并管理线程池,包括 创建线程池,销毁线程池,添加新任务;
2、工作线程(PoolWorker):线程池中线程,在没有任务时处于等待状态,可以循环的执行任务;
3、任务接口(Task):每个任务必须实现的接口,以供工作线程调度任务的执行,它主要规定了任务的入口,任务执行完后的收尾工作,任务的执行状态等;
4、任务队列(taskQueue):用于存放没有处理的任务。提供一种缓冲机制。
-- JDK 自带线程池总类介绍介绍:
1、newFixedThreadPool 创建一个指定工作线程数量的线程池。每当提交一个任务就创建一个工作线程,如果工作线程数量达到线程池初始的最大数,则将提交的任务存入到池队列中。
2、newCachedThreadPool 创建一个可缓存的线程池。这种类型的线程池特点是:
1).工作线程的创建数量几乎没有限制(其实也有限制的,数目为Interger. MAX_VALUE), 这样可灵活的往线程池中添加线程。
2).如果长时间没有往线程池中提交任务,即如果工作线程空闲了指定的时间(默认为1 分钟),则该工作线程将自动终止。终止后,如果你又提交了新的任务,则线程池重新创建一个工作线程。
3、newSingleThreadExecutor 创建一个单线程化的Executor,即只创建唯一的工作者线程来执行任务,如果这个线程异常结束,会有另一个取代它,保证顺序执行(我觉得这点是它的特色)。单工作线程最大的特点是可保证顺序地执行各个任务,并且在任意给定的时间不会有多个线程是活动的。
4、newScheduleThreadPool 创建一个定长的线程池,而且支持定时的以及周期性的任务执行,类似于Timer。(这种线程池原理暂还没完全了解透彻)
ExecutorService继承自Executor,有两个关键类实现了ExecutorService接口:ThreadPoolExecutor和ScheduledThreadPoolExecutor。
Android开发笔记之线程池的原理以及实现- https://blog.csdn.net/u012416955/article/details/52122262
android中的Executors类提供了4个工厂方法用于创建4种不同特性的线程池给开发者用.android中的线程池都是直接或是间接通过配置ThreadPoolExecutor来实现的.
-- Java通过Executors提供四种线程池,分别为:
1.newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
2.newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
3.newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
4.newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
线程池中处理线程的类别较多如:限制按顺序来执行任务的线程池;一个一个任务的执行线程池;按指定个数来执行任务的线程池;创建一个可在指定时间里执行任务的线程池,亦可重复执行、按指定工厂模式来执行的线程池.
-- 创建和封装线程池
Android 多线程 线程池原理 封装线程池- http://blog.csdn.net/smartbetter/article/details/52056272
Java通过Executors提供四种线程池- http://blog.csdn.net/mack415858775/article/details/51508831
线程池封装类—借鉴ImageLoader的线程工厂- http://blog.csdn.net/brian512/article/details/50684532
java线程池学习(二)实现一个简单的线程池- http://blog.csdn.net/great_smile/article/details/48878733
java线程池demo- http://download.csdn.net/detail/u010395804/8354097
java ThreadPoolExecutor 自定义线程池demo- http://blog.csdn.net/woshimike/article/details/53906382
线程池Demo写的很好,易理解- http://download.csdn.net/download/luoxiong94/9631946
Android开发之线程池使用总结- http://blog.csdn.net/u012702547/article/details/52259529
单例模式创建线程池和使用- https://blog.csdn.net/zhou_shaowei/article/details/54562177
java中线程池的几种实现方式- http://blog.csdn.net/w2393040183/article/details/52177572
线程池执行URL接口请求或执行代码块/函数。
-- 自定义线程池
a.自定义线程池
public void customThreadPool(View view) {
final MyThreadPool myThreadPool = new MyThreadPool(3, 5, 1, TimeUnit.MINUTES, new LinkedBlockingDeque
for (int i = 0; i < 10; i++) {
final int finalI = i;
Runnable runnable = new Runnable(){
@Override
public void run() {
SystemClock.sleep(100);
Log.d("google_lenve_fb", "run: " + finalI);
}
};
myThreadPool.execute(runnable);
}
}
class MyThreadPool extends ThreadPoolExecutor{
public MyThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
}
@Override
protected void beforeExecute(Thread t, Runnable r) {
super.beforeExecute(t, r);
Log.d("google_lenve_fb", "beforeExecute: 开始执行任务!");
}
@Override
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
Log.d("google_lenve_fb", "beforeExecute: 任务执行结束!");
}
@Override
protected void terminated() {
super.terminated();
//当调用shutDown()或者shutDownNow()时会触发该方法
Log.d("google_lenve_fb", "terminated: 线程池关闭!");
}
}
b.submit提交线程池后,取回执行结果future.get()
public void submit(View view) {
List
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(3, 5, 1,
TimeUnit.SECONDS, new LinkedBlockingDeque
for (int i = 0; i < 10; i++) {
Future
//将每一个任务的执行结果保存起来
futures.add(taskFuture);
}
try {
//遍历所有任务的执行结果
for (Future
Log.d("google_lenve_fb", "submit: " + future.get());
//future.get()
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
class MyTask implements Callable
private int taskId;
public MyTask(int taskId) {
this.taskId = taskId;
}
@Override
public String call() throws Exception {
SystemClock.sleep(1000);
//返回每一个任务的执行结果
return "call()方法被调用----" + Thread.currentThread().getName() + "-------" + taskId;
}
}
> 线程池
ExecutorService |
真正的线程池接口。 |
ScheduledExecutorService |
能和Timer/TimerTask类似,解决那些需要任务重复执行的问题。 |
ThreadPoolExecutor |
ExecutorService的默认实现。 |
ScheduledThreadPoolExecutor |
继承ThreadPoolExecutor的ScheduledExecutorService接口实现,周期性任务调度的类实现。 |
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue
}
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue
}
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue
}
// ScheduledThreadPoolExecutor
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue
ThreadFactory threadFactory) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
threadFactory, defaultHandler);
}
-- 模拟ThreadPoolExecutor的例子,以加深对线程池原理的理解:
public final class ThreadPool {
// 线程池中默认线程的个数为5
private static int worker_num = 5;
// 工作线程
private WorkThread[] workThreads;
// 任务队列,作为一个缓冲,List线程不安全
private List taskQueue = new LinkedList();
private static ThreadPool threadPool;
// 创建具有默认线程个数的线程池
private ThreadPool() {
this(5);
}
// 创建线程池,worker_num为线程池中工作线程的个数
private ThreadPool(int worker_num) {
ThreadPool.worker_num = worker_num;
workThreads = new WorkThread[worker_num];
for (int i = 0; i < worker_num; i++) {
workThreads[i] = new WorkThread();
workThreads[i].start();// 开启线程池中的线程
}
}
// 单态模式,获得一个默认线程个数的线程池
public static ThreadPool getThreadPool() {
return getThreadPool(ThreadPool.worker_num);
}
// 单态模式,获得一个指定线程个数的线程池,worker_num(>0)为线程池中工作线程的个数
// worker_num<=0创建默认的工作线程个数
public static ThreadPool getThreadPool(int worker_num1) {
if (threadPool == null)
threadPool = new ThreadPool(worker_num1);
return threadPool;
}
// 执行任务,其实只是把任务加入任务队列,什么时候执行有线程池管理器觉定
public void addTask(Runnable task) {
synchronized (taskQueue) {
taskQueue.add(task);
taskQueue. notifyAll();
}
}
// 销毁线程池,该方法保证在所有任务都完成的情况下才销毁所有线程,否则等待任务完成才销毁
public void destroy() {
while (!taskQueue.isEmpty()) {// 如果还有任务没执行完成,就先睡会吧
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 工作线程停止工作,且置为null
for (int i = 0; i < worker_num; i++) {
workThreads[i].stopWorker();
workThreads[i] = null;
}
threadPool=null;
taskQueue.clear();// 清空任务队列
}
/**
* 内部类,工作线程
*/
private class WorkThread extends Thread {
// 该工作线程是否有效,用于结束该工作线程
private boolean isRunning = true;
/*
* 关键所在啊,如果任务队列不空,则取出任务执行,若任务队列空,则等待
*/
@Override
public void run() {
Runnable r = null;
while (isRunning) {// 注意,若线程无效则自然结束run方法,该线程就没用了
synchronized (taskQueue) {
while (isRunning && taskQueue.isEmpty()) {// 队列为空
try {
taskQueue.wait(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (!taskQueue.isEmpty())
r = taskQueue.remove(0);// 取出任务
}
if (r != null) {
r.run();// 执行任务
}
r = null;
}
}
// 停止工作,让该线程自然执行完run方法,自然结束
public void stopWorker() {
isRunning = false;
}
}
}
-- Http连接池
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.HttpVersion;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpHead;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.params.HttpClientParams;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.params.ConnManagerParams;
import org.apache.http.conn.params.ConnPerRouteBean;
import org.apache.http.conn.params.ConnRouteParams;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import xiaogang.enif.utils.IOUtils;
import android.content.Context;
import android.net.Proxy;
import android.text.TextUtils;
/**
** 连接池支持http、https;
** 支持wap网络;
*/
public class HttpManager {
private static final int DEFAULT_MAX_CONNECTIONS = 30;
private static final int DEFAULT_SOCKET_TIMEOUT = 20 * 1000;
private static final int DEFAULT_SOCKET_BUFFER_SIZE = 8192;
private static DefaultHttpClient sHttpClient;
static {
final HttpParams httpParams = new BasicHttpParams();
ConnManagerParams.setTimeout(httpParams, 1000);
ConnManagerParams.setMaxConnectionsPerRoute(httpParams, new ConnPerRouteBean(10));
ConnManagerParams.setMaxTotalConnections(httpParams, DEFAULT_MAX_CONNECTIONS);
HttpProtocolParams.setVersion(httpParams, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(httpParams, "UTF-8");
HttpConnectionParams.setStaleCheckingEnabled(httpParams, false);
HttpClientParams.setRedirecting(httpParams, false);
HttpProtocolParams.setUserAgent(httpParams, "Android client");
HttpConnectionParams.setSoTimeout(httpParams, DEFAULT_SOCKET_TIMEOUT);
HttpConnectionParams.setConnectionTimeout(httpParams, DEFAULT_SOCKET_TIMEOUT);
HttpConnectionParams.setTcpNoDelay(httpParams, true);
HttpConnectionParams.setSocketBufferSize(httpParams, DEFAULT_SOCKET_BUFFER_SIZE);
SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
try {
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(null, null);
SSLSocketFactory sf = new MySSLSocketFactory(trustStore);
sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
schemeRegistry.register(new Scheme("https", sf, 443));
} catch (Exception ex) {
// do nothing, just keep not crash
}
ClientConnectionManager manager = new ThreadSafeClientConnManager(httpParams, schemeRegistry);
sHttpClient = new DefaultHttpClient(manager, httpParams);
}
private HttpManager() {
}
public static HttpResponse execute(HttpHead head) throws IOException {
return sHttpClient.execute(head);
}
public static HttpResponse execute(HttpHost host, HttpGet get) throws IOException {
return sHttpClient.execute(host, get);
}
public static HttpResponse execute(Context context, HttpGet get) throws IOException {
if (!IOUtils.isWifiAvailable(context) && isWapNetwork()) {
setWapProxy();
return sHttpClient.execute(get);
}
final HttpHost host = (HttpHost)sHttpClient.getParams().getParameter(
ConnRouteParams.DEFAULT_PROXY);
if (host != null) {
sHttpClient.getParams().removeParameter(ConnRouteParams.DEFAULT_PROXY);
}
return sHttpClient.execute(get);
}
private static void setSinaWapProxy() {
final HttpHost para = (HttpHost)sHttpClient.getParams().getParameter(
ConnRouteParams.DEFAULT_PROXY);
if (para != null) {
sHttpClient.getParams().removeParameter(ConnRouteParams.DEFAULT_PROXY);
}
String host = Proxy.getDefaultHost();
int port = Proxy.getDefaultPort();
HttpHost httpHost = new HttpHost(host, port);
HttpParams httpParams = new BasicHttpParams();
httpParams.setParameter(ConnRouteParams.DEFAULT_PROXY, httpHost);
}
public static HttpResponse execute(Context context, HttpUriRequest post) throws IOException {
if (!IOUtils.isWifiAvailable(context) && isWapNetwork()) {
setSinaWapProxy();
}
return sHttpClient.execute(post);
}
public static HttpResponse execute(Context context, HttpPost post) throws IOException {
if (!IOUtils.isWifiAvailable(context) && isWapNetwork()) {
setWapProxy();
return sHttpClient.execute(post);
}
final HttpHost host = (HttpHost)sHttpClient.getParams().getParameter(
ConnRouteParams.DEFAULT_PROXY);
if (host != null) {
sHttpClient.getParams().removeParameter(ConnRouteParams.DEFAULT_PROXY);
}
return sHttpClient.execute(post);
}
private static boolean isWapNetwork() {
final String proxyHost = android.net.Proxy.getDefaultHost();
return !TextUtils.isEmpty(proxyHost);
}
private static void setWapProxy() {
final HttpHost host = (HttpHost)sHttpClient.getParams().getParameter(
ConnRouteParams.DEFAULT_PROXY);
if (host == null) {
final String host1 = Proxy.getDefaultHost();
int port = Proxy.getDefaultPort();
HttpHost httpHost = new HttpHost(host1, port);
sHttpClient.getParams().setParameter(ConnRouteParams.DEFAULT_PROXY, httpHost);
}
}
private static class MySSLSocketFactory extends SSLSocketFactory {
SSLContext sslContext = SSLContext.getInstance("TLS");
public MySSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException,
KeyManagementException, KeyStoreException, UnrecoverableKeyException {
super(truststore);
TrustManager tm = new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
sslContext.init(null, new TrustManager[] {
tm
}, null);
}
@Override
public Socket createSocket(Socket socket, String host, int port, boolean autoClose)
throws IOException, UnknownHostException {
return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
}
@Override
public Socket createSocket() throws IOException {
return sslContext.getSocketFactory().createSocket();
}
}
}
-- Socket连接池
1. socet信息类
import java.net.Socket;
/**
* @author liuxingmi
* @DateTime 2014-8-25 下午3:21:19
* @Desc 名字服务器连接信息
*/
public class SocketInfo {
/**
* socket
*/
private Socket socket;
/**
* 是否空闲 (是:true 否:false)
*/
private boolean isFree;
/**
* socket id
*/
private Integer socketId;
/**
* 是否为可关闭链接 (是:true 否:false)
*/
private boolean isClosed;
public Socket getSocket() {
return socket;
}
public void setSocket(Socket socket) {
this.socket = socket;
}
public boolean isFree() {
return isFree;
}
public void setFree(boolean isFree) {
this.isFree = isFree;
}
public Integer getSocketId() {
return socketId;
}
public void setSocketId(Integer socketId) {
this.socketId = socketId;
}
public boolean isClosed() {
return isClosed;
}
public void setClosed(boolean isClosed) {
this.isClosed = isClosed;
}
}
2. 链接池工具
import java.io.IOException;
import java.net.Socket;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import cn.richinfo.cloudp.common.config.CloudpConfigUtil;
import cn.richinfo.cloudp.common.constant.ConfigConst;
import cn.richinfo.cloudp.common.log.DMLogger;
/**
* @author liuxingmi
* @DateTime 2014-8-25 下午3:18:18
* @Desc 分布式名字服务器socket链接池
*/
public class SocketPool {
private static DMLogger logger = DMLogger.getInstance();//日志类
/**
* socketMap
*/
public static ConcurrentHashMap
private static SocketPool instance = new SocketPool();
private SocketPool(){}
public static SocketPool getInstance(){
if(instance == null){
synchronized (SocketPool.class) {
if(instance == null){
instance = new SocketPool();
}
}
}
return instance;
}
static {
instance.initSocket(true);
}
/**
* @DateTime 2014-8-25 下午3:18:52
* @Desc 初始化链接池
* @param isAllReInit 是否全部重新初始化
* @return void
*/
public void initSocket(boolean isAllReInit){
int defaultCount = Integer.parseInt(ConfigConst.SOCKET_DEFAULT_COUNT);
logger.info("nameserver:initSocket", DMLogger.RESULT_OK, "开始初始化分布式名字服务器连接数:" + defaultCount);
for (int i = 0; i < defaultCount; i++) {
if(isAllReInit){
socketMap.put(i, setSocketInfo( i, true, false));
} else {
if(socketMap.get(i) == null || socketMap.get(i).isClosed()){
socketMap.put(i, setSocketInfo( i, true, false));
}
}
}
logger.info("nameserver:initSocket", DMLogger.RESULT_OK, "完成初始化分布式名字服务器连接数");
new CheckSocketThread().start();
}
/**
* @DateTime 2014-8-26 上午10:06:13
* @Desc 设置socketInfo值
* @param socket
* @param key
* @param isFree
* @param isClosed
* @return SocketInfo
*/
private static SocketInfo setSocketInfo(Integer key, boolean isFree, boolean isClosed){
SocketInfo socketInfo = new SocketInfo();
Socket socket = createSocket();
socketInfo.setFree(isFree);
socketInfo.setSocket(socket);
socketInfo.setSocketId(key);
socketInfo.setClosed(isClosed);
return socketInfo;
}
/**
* @DateTime 2014-8-25 下午3:19:06
* @Desc 获取名字服务器链接
* @return
* SocketInfo
*/
public SocketInfo getSocketInfo(){
SocketInfo socketInfo = null;
if(socketMap.size() < Integer.parseInt(ConfigConst.SOCKET_DEFAULT_COUNT)){
initSocket(false);
}
if(socketMap.size() > 0){
for (Map.Entry
socketInfo = entry.getValue();
if(socketInfo.isFree() && ! socketInfo.getSocket().isClosed()){
socketInfo.setFree(false);
return socketInfo;
}
}
} else {
logger.info("nameserver:socketInfo", DMLogger.RESULT_FAIL, "名字服务器socket连接池数量为零。");
return null;
}
logger.info("nameserver:socketInfo", DMLogger.RESULT_OK, "所有名字服务器socket链接都忙,创建临时链接。");
socketInfo = setSocketInfo(-1, true, true);
logger.info("nameserver:socketInfo", DMLogger.RESULT_OK, "成功创建服务器socket临时链接。");
return socketInfo;
}
/**
* 释放socket
* @param socketId
*/
public static void distorySocket(Integer socketId){
logger.debug("nameserver:distorySocket", DMLogger.RESULT_OK, "释放名字服务器socket链接。");
SocketInfo socketInfo = socketMap.get(socketId);
socketInfo.setFree(true);
}
/**
* @DateTime 2014-8-25 下午3:19:42
* @User liuxingmi
* @Desc 释放socket
* @param socketInfo
* void
*/
public static void distorySocket(SocketInfo socketInfo){
if(socketInfo == null) return;
if( ! socketInfo.isClosed()){
logger.debug("nameserver:distorySocket", DMLogger.RESULT_OK, "链接池socket,释放资源。");
distorySocket(socketInfo.getSocketId());
return;
}
logger.debug("nameserver:distorySocket", DMLogger.RESULT_OK, "可关闭临时链接,关闭socket");
try {
if(socketInfo.getSocket() != null){
socketInfo.getSocket().close();
}
} catch (IOException e) {
logger.error("nameserver:distorySocket", DMLogger.RESULT_FAIL, "关闭名字服务器socket链接失败", e);
}
socketInfo = null;
}
/**
* @DateTime 2014-8-25 下午3:19:51
* @Desc 创建socket
* @return
* Socket
*/
public static Socket createSocket(){
String nameServerip1 = CloudpConfigUtil.DM_CONFIG.getNameSerIP1();
int namServerport1 = CloudpConfigUtil.DM_CONFIG.getNameSerPort1();
String nameServerip2 = CloudpConfigUtil.DM_CONFIG.getNameSerIP2();
int namServerport2 = CloudpConfigUtil.DM_CONFIG.getNameSerPort2();
Socket socket = null;
try {// 尝试通过ip1第一次建立连接
socket = new Socket(nameServerip1, namServerport1);
logger.info("nameserver:login", DMLogger.RESULT_OK, "nameServerip1:" + nameServerip1 + ", namServerport1:" + namServerport1);
} catch (IOException e) {
logger.error("nameserver:login", DMLogger.RESULT_FAIL, "first link fail nameServerip1:" + nameServerip1 + ", namServerport1:" + namServerport1, e);
try {
// 如果第一次通过ip1建立连接失败,则进行第二次连接
socket = new Socket(nameServerip2, namServerport2);
logger.info("nameserver:login", DMLogger.RESULT_OK, "nameServerip2:" + nameServerip2 + ", namServerport2:" + namServerport2);
} catch (IOException e1) {
logger.error("nameserver:login", DMLogger.RESULT_FAIL, "second link fail nameServerip2:" + nameServerip2 + ", namServerport2:" + namServerport2, e);
return null;
}
}
return socket;
}
class CheckSocketThread extends Thread{
@Override
public void run() {
while (true) {
logger.debug("nameserver:checkSocket", DMLogger.RESULT_OK, "开始检测分布式链接状态。");
if(socketMap.size() < Integer.parseInt(ConfigConst.SOCKET_DEFAULT_COUNT)){
logger.info("nameserver:checkSocket", DMLogger.RESULT_OK, "分布式名字服务器socket链接小于默认链接数,增加socket链接。");
initSocket(false);
}
for (Map.Entry
SocketInfo socketInfo = entry.getValue();
if(socketInfo.getSocket() == null || socketInfo.isClosed()){
logger.error("nameserver:checkSocket", DMLogger.RESULT_FAIL, "第"+ entry.getKey()+"个socket链接已关闭,重新连接分布式。",null);
socketInfo.setSocket(createSocket());
} else {
if(socketInfo.isFree()){
boolean flag = NameServerUtils.getInstance().checkHeartbeat(socketInfo);
if( ! flag ){
logger.error("nameserver:checkSocket", DMLogger.RESULT_FAIL, "第"+ entry.getKey()+"个socket链接失败,重新连接分布式。",null);
socketInfo.setSocket(createSocket());
continue;
}
}
logger.debug("nameserver:checkSocket", DMLogger.RESULT_OK, "第"+ entry.getKey()+"个socket链接正常。");
}
}
try {
sleep(Long.valueOf(ConfigConst.SOCKET_CHECK_TIME));
} catch (Exception e) {
}
}
}
}
}