线程池-ThreadPoolExecutor

线程池-ThreadPoolExecutor

使用场景

想要频繁的创建和销毁线程的时候

线程池的概念

线程池就是提前创建若干个线程,如果有任务需要处理,线程池里的线程就会处理任务,处理完之后线程并不会被销毁,而是等待下一个任务。由于创建和销毁线程都是消耗系统资源的

线程池的优势

  • 降低创建线程和销毁线程的性能开销
  • 提高响应速度,当有新任务需要执行是不需要等待线程创建就可以立马执行
  • 合理的设置线程池大小(限流)可以避免因为线程数超过硬件资源瓶颈带来的问题

Api Executors

  1. newFixedThreadPool

    该方法返回一个固定数量的线程池,当有一个任务提交时,若线程池中空闲,则立即执行,若没有,则会被暂缓在一个任务队列中,等待有空闲的线程去执行,用途:FixedThreadPool 用于负载比较大的服务器,为了资源的合理利用,需要限制当前线程数量。
    ThreadPoolExecutor(corePoolSize, maximumPoolSize, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue());

  2. newSingleThreadExecutor

    创建一个线程的线程池,若空闲则执行,若没有空闲线程则暂缓在任务队列中。ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue());

  3. newCachedThreadPool

    根据实际情况调整线程个数,不限制最大线程数,若用空闲的线程则执行任务,若无任务则不创建线程。并且每一个空闲线程会在 60 秒后自动回收。ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue());

  4. newScheduledThreadPool

    创建一个可以指定线程的数量的线程池,但是这个线程池还带有延迟和周期性执行任务的功能,类似定时器。ThreadPoolExecutor(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue(), threadFactory);

线程池参数

线程池中线程总数、运行线程数、空闲线程数、任务队列等之间的关系

  1. 当【运行的线程数 < corePoolSize】,则直接创建新线程来处理任务,即使线程池中的其他线程是空闲的
  2. 当【corePoolSize <= 线程池中线程数 < maximumPoolSize】,则只有当workQueue满时,才创建新线程处理
  3. 当【corePoolSize = maximumPoolSize】,在workQueue没满时,那么请求会放入workQueue,等待空闲线程去除任务处理
  4. 当【运行的线程数 > maximumPoolSize】,如果workQueue已满,那么会根据指定策略来处理提交过来的任务
  ThreadPoolExecutor(int corePoolSize,                  //核心线程数
                     int maximumPoolSize,               //最大线程数
                     long keepAliveTime,                //超出核心线程数量以外的线程空余存活时间
                     TimeUnit unit,                     //存活时间单位
                     BlockingQueue<Runnable> workQueue, //保存执行任务的队列
  				    ThreadFactory threadFactory,       //创建新线程使用的工厂
                     RejectedExecutionHandler handler)  //当任务无法执行的时候的处理方式

任务提交

  1. execute();//任务提交
  2. submit(); //带有返回值的任务提交

最佳线程数

最佳线程数目 = (线程等待时间+任务执行时间)/任务执行时间 * CPU数目

备注:这个公式也是前辈们分享的,当然之前看了淘宝前台系统优化实践的文章,和上面的公式很类似,不过在CPU数目那边,他们更细化了,上面的公式只是参考。不过不管什么公式,最终还是在生产环境中运行后,再优化调整。

例如服务器CPU核数为4核,一个任务线程cpu耗时为20ms,线程等待(网络IO、磁盘IO)耗时80ms,那最佳线程数目:( 80 + 20 )/20 * 4 = 20。也就是设置20个线程数最佳。

上一篇:阻塞队列和线程池


下一篇:java之多线程--线程池