线程池的使用以及实现原理

一.线程池的使用

  1.并发包线程池的体系

   java.util.concurrent.Executor : 负责线程的使用与调度的根接口 

   |–ExecutorService:Executor的子接口,线程池的主要接口 
   |–ThreadPoolExecutor:ExecutorService的实现类 ,一般就是用这个来创建线程池。阿里的java开发手册有提到不要使用Executor去创建线程池   
   |–ScheduledExecutorService:ExecutorService的子接口,负责线程的调度 
     |–ScheduledThreadPoolExecutor:既继承了ThreadPoolExecutor,同时实现了ScheduledExecutorService

  2.创建线程池的方式

    1.通过Executors ,这种方式很简单,它已经封装好几种线程池给你使用了,但是有一些参数你无法设置,可能会有资源耗尽的风险,主要有四种常见的线程池,如下:

 

     ExecutorService cacheThreadPool = Executors.newCachedThreadPool();
        /*优点:很灵活,弹性的线程池线程管理,用多少线程给多大的线程池,不用后及时回收,用则新建。使用SynchronousQueue
     缺点:一旦线程无限增长,会导致内存溢出*/ 
     ExecutorService ec
= Executors.newFixedThreadPool(0);

     /*优点:创建一个固定大小线程池,超出的线程会在队列中等待。使用LinkedBlockingDeque

         缺点:不支持自定义拒绝策略,大小固定,难以扩展*/ 
     ExecutorService ss
= Executors.newSingleThreadExecutor();

     //优点:创建一个单线程的线程池,保证线程的顺序执行,有啥用?使用LinkedBlockingDeque
     //缺点:请求处理队列可能会耗费非常大的内存,甚至 OOM
ExecutorService sss
= Executors.newScheduledThreadPool(1); /* 优点:创建一个固定大小线程池,可以定时或周期性的执行任务。 缺点:任务是单线程方式执行,一旦一个任务失败其他任务也受影响*/

   2.通过ThreadPoolExecutor创建,这也是阿里的java开发手册推荐的,其实上面的线程池工具类底层就是通过这个来创建线程池的,具体操作看下面代码:

     我们来关注一下里面的参数:

    1.线程池的大小:这里面有两个参数,核心线程数和最大总线程数,本来线程池里面一个线程都没有,开始创建的线程就是核心线程,然后,等线程池里面的线程数超过核心线程数之后,会加入阻塞队列,等到这个队列都满了,就创建新的线程去执行任务,等线程数到达最大线程数后,RejectedExecutionHandler来执行拒绝策略。

    2.阻塞队列:ArrayBlockingQueue :一个由数组结构组成的有界阻塞队列。
          LinkedBlockingQueue :一个由链表结构组成的有界阻塞队列。
          PriorityBlockingQueue :一个支持优先级排序的无界阻塞队列。
          DelayQueue: 一个使用优先级队列实现的无界阻塞队列。
          SynchronousQueue: 一个不存储元素的阻塞队列。
          LinkedTransferQueue: 一个由链表结构组成的无界阻塞队列。
          LinkedBlockingDeque: 一个由链表结构组成的双向阻塞队列。

    3.拒绝策略:ThreadPoolExecutor.AbortPolicy: 丢弃任务并抛出RejectedExecutionException异常。 (默认)
          ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。
          ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复过程)
          ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务

//用ThreadPoolExecutor创建线程池
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( corePoolSize, //线程池核心池的大小。 maximumPoolSize, //线程池的最大线程数 keepAliveTime, //当线程数大于核心时,此为终止前多余的空闲 //线程等待新任务的最长时间。 unit, //keepAliveTime 的时间单位 workQueue, //用来储存等待执行任务的队列 threadFactory, //线程工厂 handler); //拒绝策略



//这是它的构造方法
public ThreadPoolExecutor(int corePoolSize,
                               int maximumPoolSize,
                               long keepAliveTime,
                               TimeUnit unit,
                               BlockingQueue<Runnable> workQueue,
                              RejectedExecutionHandler handler) 
 

   

posted @ 2018-11-15 23:03  AJimmyFang  阅读(445)  评论(0编辑  收藏  举报