前言

线程经常用,线程池也用,但在于如何使用,没有记录一下。

本文参考别人文章整理。

正文

使用线程池的好处

  1. 降低内存资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
  2. 提高响应速度。在线程池中的线程都是已经被创建好的,我们的任务直接获取一个空闲的线程就能够被执行了
  3. 提高线程的可管理性。使用线程池可以进行统一分配、调优和监控。线程是稀缺资源,如果无限制地创建,不仅会消耗系统资源,还会降低系统的稳定性。

ThreadPoolExecutor构造参数详解

比如

/**
* 参数信息:
* int corePoolSize     核心线程大小
* int maximumPoolSize  线程池最大容量大小
* long keepAliveTime   线程空闲时,线程存活的时间
* TimeUnit unit        时间单位
* BlockingQueue<Runnable> workQueue  任务队列。一个阻塞队列
* threadFactory :
* RejectedExecutionHandler :新建线程工厂 当提交任务数超过maxmumPoolSize+workQueue之和时,任务会交给RejectedExecutionHandler来处理
*/
mThreadPoolExecutor = new ThreadPoolExecutor(2, 4, 5, TimeUnit.SECONDS,  new ArrayBlockingQueue<>(2), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
  1. corePoolSize : 核心线程池大小
  2. maximumPoolSize : 最大线程池大小
  3. keepAliveTime : 线程池中超过corePoolSize数目的空闲线程最大存活时间;可以allowCoreThreadTimeOut(true)使得核心线程有效时间
  4. TimeUnit : keepAliveTime时间单位
  5. workQueue : 阻塞任务队列
  6. threadFactory : 新建线程工厂
  7. RejectedExecutionHandler : 当提交任务数超过maxmumPoolSize+workQueue之和时,任务会交给RejectedExecutionHandler来处理
corePoolSize,maximumPoolSize,workQueue之间关系
  1. 当线程池小于corePoolSize时,新提交任务将创建一个新线程执行任务,即使此时线程池中存在空闲线程。
  2. 当线程池达到corePoolSize时,新提交任务将被放入workQueue中,等待线程池中任务调度执行
  3. 当workQueue已满,且maximumPoolSize>corePoolSize时,新提交任务会创建新线程执行任务
  4. 提交任务数超过maximumPoolSize时,新提交任务由RejectedExecutionHandler处理
  5. 线程池中超过corePoolSize线程,空闲时间达到keepAliveTime时,关闭空闲线程
  6. 当设置allowCoreThreadTimeOut(true)时,线程池中corePoolSize线程空闲时间达到keepAliveTime也将关闭

如何使用线程池

mThreadPoolExecutor.execute(Runnable);

mThreadPoolExecutor.submit(Runnable);

execute()和submit()区别

  1. execute()是ThreadPoolExecutor的方法
  2. submit()是ExecutorService的方法
  3. execute(..) 方法用于提交不需要返回值的任务,所以无法判断任务是否被线程池执行成功。
  4. submit(..) 方法用于提交需要返回值的任务。线程池会返回一个 future 类型的对象,通过这个 future 对象可以判断任务是否执行成功,并且可以通过 future 的 get() 方法来获取返回值,get() 方法会阻塞当前线程直到任务完成,而使用 get(long timeout,TimeUnit unit)方法则会阻塞当前线程一段时间后立即返回,这时候有可能任务没有执行完。

Executors提供的线程池配置方案

构造一个固定线程数目的线程池,配置的corePoolSize与maximumPoolSize大小相同,同时使用了一个无界LinkedBlockingQueue存放阻塞任务,因此多余的任务将存在再阻塞队列,不会由RejectedExecutionHandler处理
public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }
构造一个缓冲功能的线程池,配置corePoolSize=0,maximumPoolSize=Integer.MAX_VALUE,keepAliveTime=60s,以及一个无容量的阻塞队列 SynchronousQueue,因此任务提交之后,将会创建新的线程执行;线程空闲超过60s将会销毁
public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }
构造一个只支持一个线程的线程池,配置corePoolSize=maximumPoolSize=1,无界阻塞队列LinkedBlockingQueue;保证任务由一个线程串行执行
public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }

参考文章

  1. ThreadPoolExecutor使用详解
  2. 《[ThreadPoolExecutor的使用])(https://blog.csdn.net/Day_and_Night_2017/article/details/124404629)》
  3. ThreadPoolExecutor的使用方法
  4. Java多线程 ThreadPoolExecutor-RejectedExecutionHandler拒绝执行策略
  5. 线程池ThreadPoolExecutor的使用详解

相关文章

暂无评论

none
暂无评论...