zoukankan      html  css  js  c++  java
  • java线程池ThreadPoolExecutor理解

    Java通过Executors提供四种线程池,分别为:
    newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
    newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
    newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
    newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

    熟悉这四种线程池,首先 先了解ThreadPoolExecutor

    ThreadPoolExecutor中定义了以下几个属性比较重要

    corePoolSize:线程池中的线程数量,线程池中默认开启几个线程处理 任务队列中的任务

      (注:这个并不是固定的,根据队列(workQueue)的不同实现类型而改变)

    maximumPoolSize:线程池中的最大线程数量,这个属性感觉和上面的corePoolSize冲突,明明上面定义了线程数据了,怎么这里又控制了

    最大线程数量,其实 一样和 上面提到的一样(根据队列(workQueue)的不同实现类型 ,需要用到该属性进行相应的 任务拒绝策略)

    keepAliveTime;//超过corePoolSize的空闲线程,在多长时间内会被销毁
    TimeUnit unit;//keepAliveTime的单位
    BlockingQueue<Runnable> workQueue:任务队列,被提交的但尚未被执行的任务

    主要有以下几种实现类型

    SynchronousQueue:直接提交的队列,该队列没有容量,每一个擦入操作都要对应一个相应的删除操作,反之每个删除操作对应相应的插入操作。

               SynchronousQueue不保存任务,它总是将任务提交给线程执行,如果没有空闲的进程,则尝试创建新的进程,如果进程

              已达到maximumPoolSize设置的最大线程数,则执行拒绝策略

    ArrayBlockingQueue:有界任务队列,ArrayBlockingQueue的构造函数必须带一个容量参数(例如n),表示该队列的最大容量。

                 当有新任务执行时,这个定义当前线程数为t,构造函数的容量参数为n,当前队列长度为l

               1.t<corePoolSize时,创建新的线程之心

                                   2.t>corePoolSize且l<n时,插入到任务队列,等待空闲线程执行

                                   3.t>corePoolSize且l>=n时,创建新的线程执行新任务

                                   4.t>maximumPoolSize时,执行拒绝策略。

    LinkedBlockingQueue:无界任务队列,当有新任务执行时,如果线程池中线程数小于corePoolSize则创建新的线程,否则进入队列等待。

               如果没有任务创建速度和处理速度差异很大,无界队列会保持快速增长,直到耗尽系统内存

      PriorityBlockingQueue:优先级队列,可以控制任务的执行先后顺序,是一个特殊的无界队列。无论有界的队列无界的队列,都是按照先进先出算法

                 处理任务(絮叨),而该队列破例可以根据任务自身的优先级顺序先后执行。

    ThreadFactory threadFactory//线程工厂,用于创建线程,一般默认
    RejectedExecutionHandler handler;//拒绝策略,当任务太多来不及处理,如何拒绝任务

      JDK内置的拒绝策略如下:

      AbortPolity策略:该策略会直接抛出异常,阻止系统正常工作

      CallerRunsPolity策略:只要线程为关闭,该策略直接在调用者线程中,运行当前被丢弃的任务

          DiscardOledstPolicy策略:该策略将丢弃最老的一个请求,也就是即将被执行的一个任务,并尝试再次提交当前任务。

      DiscardPlicy 策略:该策略默默的丢弃无法处理的任务,不予任务处理。

    如果以上策略不能满足实际应用需求,可以扩展RejectedExecutionHandler 接口

    public interface RejectedExecutionHandler {
    
        void rejectedExecution(Runnable r, ThreadPoolExecutor executor);
    }

    其中,r为请求执行的任务,executor为当前线程池。

    了解了ThreadPoolExecutor的上述属性,然后分析Executors提供四种线程池就很简单了

    Executors.newFixedThreadPool(nThreads) 

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

    返回了一个corePoolSize, maximumPoolSize大小相等并且使用了LinkedBlockingQueue任务队列的线程池,因为对于固定大小的线程池而言,不存在线程数量的动态

    变化,因此corePoolSize,和maximumPoolSize可以相等,同时它使用无界队列存放无法立即执行的任务,当任务提交非常频繁的时候,该队列可能迅速膨胀,从而耗尽

    系统资源。

    Executors.newSingleThreadExecutor()

        public static ExecutorService newSingleThreadExecutor() {
            return new FinalizableDelegatedExecutorService
                (new ThreadPoolExecutor(1, 1,
                                        0L, TimeUnit.MILLISECONDS,
                                        new LinkedBlockingQueue<Runnable>()));
        }

    返回单线程的线程池,是newFixedThreadPool()方法的一种退化,只是简单的将线程池的线程数量设置为1

    Executors.newCachedThreadPool()

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

    返回corePoolSize为0 maximumPoolSize无穷大的线程池,这意味着在没有任务时,该线程内无线程,而当任务被提交时,该线程池会使用空闲的线程执行任务,若无空闲

    线程,则将任务加入SynchronousQueue队列,而SynchronousQueue队列是一种直接提交的队列,它总会迫使线程池增加新的线程执行任务,当任务执行完毕后,

    由于corePoolSize为0,因此空线程又会在指定时间内(60s)被回收。

    对于newCachedThreadPool(),如果同时又大量任务被提交,而任务的执行又不那么快时,那么系统便会开启等量的线程处理,这样的做法可能会很快耗尽系统的资源。

  • 相关阅读:
    Python开篇——Python的哲学
    python在CentOS 7中的安装
    TortoiseSVN_1.9.1.267_x64版本控制系统(针对Visual SVN Server)使用简单介绍
    win10+eclipse+hadoop2.7.2+maven+local模式直接通过Run as Java Application运行wordcount
    存储器的保护(三)——《x86汇编语言:从实模式到保护模式》读书笔记20
    存储器的保护(一)——《x86汇编语言:从实模式到保护模式》读书笔记18
    存储器的保护(二)——《x86汇编语言:从实模式到保护模式》读书笔记19
    进入保护模式(三)——《x86汇编语言:从实模式到保护模式》读书笔记17
    16位模式/32位模式下PUSH指令探究——《x86汇编语言:从实模式到保护模式》读书笔记16
    关于80286——《x86汇编语言:从实模式到保护模式》读书笔记15
  • 原文地址:https://www.cnblogs.com/liuxiuhao/p/5728142.html
Copyright © 2011-2022 走看看