为什么引进线程池 鱼池,我们可以钓出来一条再放回去,钓出来一条再放回去,这样来撩鱼。 那线程池该如何玩呢?对,取出来一“条”线程,用完后再扔回去,再取出来,再扔.... 线程池的优点: 避免大量的创建和销毁带来的性能开销 避免大量的线程间因互相抢占系统资源导致的阻塞现象。 能够对线程进行简单的管理并提供定时执行、间隔执行等功能。 缺点 占用一定的内存空间。 线程越多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接口,达到指定时间后,方可执行任务

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