线程精进指南之线程池进阶

为何引进线程池
鱼池,咱们能够钓出来一条再放回去,钓出来一条再放回去,这样来撩鱼。缓存

那线程池该如何玩呢?对,取出来一“条”线程,用完后再扔回去,再取出来,再扔....ide

线程池的优势:性能

避免大量的建立和销毁带来的性能开销线程

避免大量的线程间因互相抢占系统资源致使的阻塞现象。设计

可以对线程进行简单的管理并提供定时执行、间隔执行等功能。code

缺点对象

占用必定的内存空间。接口

线程越多CPU的调度开销越大。队列

程序的复杂度会上升。内存

线程池的基本使用
使用线程池 ,确定要对“池”进行配置,像基本的池多大啊,能容纳多少鱼啊,等这些是须要建造前就要肯定的,所以咱们搞池以前先设计

• int corePoolSize 核心线程最大数

 不管是闲置仍是工做中,永远都不会销毁的线程,会一直在线程池中存在,那咱们是否是永远都奈何不了它呢,固然不会,把ThreadPoolExecutor的allowCoreThreadTimeOut这个属性设置为true,超过规定时长也会销毁

• int maximumPoolSize 线程总数最大值

 就是咱们全部的线程啊,对,包括非核心的和上边讲的核心的

• long keepAliveTime

 若是不是核心线程,超过这个参数的时间就会被干掉

• TimeUnit unit

 时间老是有单位的吧,对就是上边KeepAliveTime的时间参数哇

 类型时枚举,这里举几种经常使用的,反正说多了也记不住,须要时候IDEA会提示

 SECONDS : 秒

 MINUTES : 分

 HOURS : 小时

 DAYS : 天

• BlockingQueue workQueue  

 队列内容较多,咱们下边单独讲

• ThreadFactory threadFactory

 这个通常不用,不必管啦

• RejectedExecutionHandler handler

 若是执行的过程当中,抛异常了,咱们能够用这个来指定,可是系统有默认的,所以这个也能够不用

 

使用线程池固然离不开Executor这个接口,具体的实现类在ThreadPoolExecutor中,so咱们简单了解下这个类

//对,使用的就是这几个构造,参数咱们上边已经将过了

public class ThreadPoolExecutor extends AbstractExecutorService {
    .....
    public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long  keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue);
 
    public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory);
 
    public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,RejectedExecutionHandler handler);
 
    public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler);
    ...
}

 

经常使用的几种线程池
线程都池都是是使用Executors这个类建立出来的

• CachedThreadPool()

 可缓存线程池:

 线程数无限制

 优先使用空闲线程,若是没有才新建线程

 //建立方式
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();

//源码中的定义

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

 

• FixedThreadPool()

 固定长度的线程池

 能够控制线程的数量

 若是超过则必须排队执行

 //建立方式
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(线程数量);

//源码中的定义

public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>());
}

• ScheduledThreadPool()

 对,就是它能够定时

 //建立方法
ExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(最大线程数);

//源码中的定义

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
    return new ScheduledThreadPoolExecutor(corePoolSize);
}

public ScheduledThreadPoolExecutor(int corePoolSize) {
    super(corePoolSize, Integer.MAX_VALUE,
          DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
          new DelayedWorkQueue());
}

• SingleThreadExecutor()

 全部任务排队执行,一次只能执行一个任务

 //建立方法
ExecutorService singleThreadPool = Executors.newSingleThreadPool();

//源码中的定义

public static ExecutorService newSingleThreadExecutor() {
    return new FinalizableDelegatedExecutorService
        (new ThreadPoolExecutor(1, 1,
                                0L, TimeUnit.MILLISECONDS,

                                new LinkedBlockingQueue<Runnable>()));

队列
队列相似咱们的集合,实现了Collection接口

队列中排队执行的是咱们runnable对象

经常使用的队列有以下几种

• SynchronousQueue:

 有任务来就执行交给空闲线程,若是没有就新建线程执行,so 线程数设置尽量大即Integer.MAX_VALUE

• LinkedBlockingQueue:

 永远在核心线程内使用线程,若是超过了核心的线程就在队列中等待执行

• ArrayBlockingQueue:

 优先使用核心线程数,其次使用非核心的,若是用完了就进入队列等待

• DelayQueue:

 想进入队列必须实现Delayed接口,达到指定时间后,方可执行任务

 

读书百遍不如代码十遍,提高的惟一道路惟有你的手速!

相关文章
相关标签/搜索