线程池原理,安全停止线程(池),Http与Socket连接池-(Android/Java)

深入理解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<Runnable>(1024), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy());
public static void main(String[] args) {

        for (int i = 0; i < Integer.MAX_VALUE; i++) {
              pool.execute(new SubThread());
        }
    }
}

- 线程池执行流程:

https://img-blog.csdnimg.cn/20181110105122433.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1NoYXJlVXM=,size_16,color_FFFFFF,t_70

> 停止线程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<Runnable>());  
    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<Runnable> workQueue) {  
        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<Future<String>> futures = new ArrayList<>();  
    ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(3, 5, 1,  
            TimeUnit.SECONDS, new LinkedBlockingDeque<Runnable>());  
    for (int i = 0; i < 10; i++) {  
        Future<String> taskFuture = threadPoolExecutor.submit(new MyTask(i));  
        //将每一个任务的执行结果保存起来  
        futures.add(taskFuture);  
    }  
    try {  
        //遍历所有任务的执行结果  
        for (Future<String> future : futures) {  
            Log.d("google_lenve_fb", "submit: " + future.get());  
   //future.get()
        }  
    } catch (InterruptedException e) {  
        e.printStackTrace();  
    } catch (ExecutionException e) {  
        e.printStackTrace();  
    }  
}  
class MyTask implements Callable<String> {    
    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<Runnable>());
    }
 
public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }

public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

// ScheduledThreadPoolExecutor
public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              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<Runnable> taskQueue = new LinkedList<Runnable>();

     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<Integer, SocketInfo> socketMap = new ConcurrentHashMap<Integer, SocketInfo>();
  
  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<Integer, SocketInfo> entry : socketMap.entrySet()) {
        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<Integer, SocketInfo> entry : socketMap.entrySet() ) {
          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) {
        } 
      }
    }
  }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值