ThreadPoolExecutor应用

来源:互联网 发布:pyqt5 windows 编辑:程序博客网 时间:2024/06/13 02:19

当需要创建多个线程执行任务时,不建议手动建创线程,可使用ThreadPoolExecutor线程池执行,提高性能。

  • ThreadPoolExecutor参数

    public ThreadPoolExecutor(int corePoolSize,                      int maximumPoolSize,                      long keepAliveTime,                      TimeUnit unit,                      BlockingQueue<Runnable> workQueue,                      RejectedExecutionHandler handler)

    corePoolSize:线程池中保留的最大线程数
    maximumPoolSize:线程池中最大线程数
    keepAliveTime:线程空闲的保持时间
    unit:keepAliveTime的时间单位
    workQueue:任务队列
    handler:无空闲线程,且已到最大线程数时,新来任务时的处理

  • 执行过程

    当线程池中的线程数小于corePoolSize时,若新来任务会重新起一个线程执行;
    当线程池中线程等于corePoolSize时,若新来任务会放到workQueue队列中去,等待有空闲线程时执行;
    当workQueue队列中任务已满,但线程数还没达到maximunPoolSize时,重新起一个线程执行;
    当线程达到maximunPoolSize时,会执行handler来处理新任务;
    当线程中的任务执行完后,会在队列中获取新任务执行;
    当队列及线程中的任务执行完成后,若线程数多于corePoolSize时会在等待keepAliveTime时间后结束掉,否则不结束。最终线程池中的线程数会小于或等于corePoolSize。

  • 队列的三种方式

    1. SynchronousQueue
      直接提交。直接将任务提交给线程而不保持它们。此队列只有在任务被取走后才会添加新任务,且没有任何内部容量,也不能调用peek()方法查看队列中是否有内容,因为只有任务被取走时才会存在。可以说是大小为1的阻塞队列。因此,在使用此队列时,最好maximunPoolSize为无界。而此队列的作用是:可以避免在处理可能具有内部依赖性的请求集时出现锁。比如有A,B两个任务要执行,但必须要先执行A再执行B,那么此队列就可以保证其顺序,因为只有在A被移除之后B才会添加进来。

    2. LinkedBlockingQueue
      无界队列。当运行的线程数等于maximunPoolSize,继续新来任务时则会直接加入此对列中,不再增加新的线程。若没有空闲线程,且不断的增加新任务时,容易引发资源耗尽。

    3. ArrayBlockingQueue
      有界队列。防止资源耗尽,但要协调线程数和队列长度,较难把握。

  • RejectedExecutionHandler 拒绝处理

    1. AbortPolic:任务遭到拒绝将抛出异常RejectedExecutionException,并丢弃任务。
    2. DiscardPolicy:直接丢弃任务。
    3. DiscardOldestPolicy:如果执行程序还未关闭,则位于队列头部的任务将被删除,新任务进入队列。
  • 建议
    可以使用Executors类,里面包含了大多数的executor。如果编写的是小程序,或轻载服务器,可选择使用Executors.new CachedThreadPool,不需要配置,能正确完成工作,其中里面的队列使用的是SynchronousQueue,当任务全部结束时,线程池中的线程数为0。但对于大负载的服务器来说,缓存的线程池不太合适。如果负载太重,不停的创建新线程,cpu全被占用。因此最好使用Executors.new FixedThreadPool,包含固定的线程数,其中里面的队列使用的是LinkedBlockingQueue。如果想更好控制就直接使用ThreadPoolExecutor类。

0 0
原创粉丝点击