zoukankan      html  css  js  c++  java
  • 线程池与Executor框架

    线程池

    线程池的实现原理

    1)线程池判断核心线程池里的线程是否都在执行任务。如果不是,则创建一个新的工作线程来执行任务。如果核心线程池里的线程都在执行任务,则进入下个流程。

    2)线程池判断工作队列是否已经满。如果工作队列没有满,则将新提交的任务存储在这个工作队列里。如果工作队列满了,则进入下个流程。

    3)线程池判断线程池的线程是否都处于工作状态。如果没有,则创建一个新的工作线程来执行任务。如果已经满了,则交给饱和策略来处理这个任务。

     

    线程池的创建

    我们可以通过ThreadPoolExecutor来创建一个线程池。

    new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime,

    milliseconds,runnableTaskQueue, handler);

    1)corePoolSize(线程池的基本大小)

    2)runnableTaskQueue(任务队列)

    a)ArrayBlockingQueue:是一个基于数组结构的有界阻塞队列,此队列按FIFO(先进先出)原则对元素进行排序。

    b)LinkedBlockingQueue:一个基于链表结构的阻塞队列,此队列按FIFO排序元素,吞吐量通常要高于ArrayBlockingQueue。

    c)SynchronousQueue:一个不存储元素的阻塞队列。每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,吞吐量通常要高于Linked-BlockingQueue

    d)PriorityBlockingQueue:一个具有优先级的无限阻塞队列。

    3)maximumPoolSize(线程池最大数量)

    4)ThreadFactory:用于设置创建线程的工厂

    5)RejectedExecutionHandler(饱和策略): 默认情况下是AbortPolicy

    a)AbortPolicy:直接抛出异常。

    b)CallerRunsPolicy:只用调用者所在线程来运行任务。

    c)DiscardOldestPolicy:丢弃队列里最近的一个任务,并执行当前任务。

    d)DiscardPolicy:不处理,丢弃掉。

    6) keepAliveTime(线程活动保持时间)

    7) TimeUnit(线程活动保持时间的单位)

    向线程池提交任务

    可以使用两个方法向线程池提交任务,分别为execute()和submit()方法。

    execute()方法:用于提交不需要返回值的任务,所以无法判断任务是否被线程池执行成功。execute()方法输入的任务是一个Runnable类的实例。

     

    submit()方法:用于提交需要返回值的任务。线程池会返回一个future类型的对象,通过这个

    future对象可以判断任务是否执行成功,并且可以通过future的get()方法来获取返回值,get()方法会阻塞当前线程直到任务完成,而使用get(long timeout,TimeUnit unit)方法则会阻塞当前线程一段时间后立即返回,这时候有可能任务没有执行完。

    关闭线程池

    可以通过调用线程池的shutdown或shutdownNow方法来关闭线程池。

    shutdownNow:首先将线程池的状态设置成STOP,然后尝试停止所有的正在执行或暂停任务的线程,并返回等待执行任务的列表

    Shutdown:只是将线程池的状态设置成SHUTDOWN状态,然后中断所有没有正在执行任务的线程。

     

    Executor框架

    Executor框架的主要成员:ThreadPoolExecutor、ScheduledThreadPoolExecutor、

    Future接口、Runnable接口、Callable接口和Executors。

    ThreadPoolExecutor

    通常使用工厂类Executors来创建。Executors可以创建3种类型的

    ThreadPoolExecutor:SingleThreadExecutor、FixedThreadPool和CachedThreadPool。

    FixedThreadPool

    ①CorePoolSize = maximumPoolSize = nThreads

    ②keepAliveTime=0L

    ③使用无界队列LinkedBlockingQueue

     

    SingleThreadExecutor

    ①corePoolSize = maximumPoolSize = 1

    ②使用无界队列LinkedBlockingQueue

     

    CachedThreadPool

    ①corePoolSize = 0

    ②maximumPoolSize = Integer.MAX_VALUE

    ③ keepAliveTime = 60L

    ④使用没有容量的SynchronousQueue

     

    ScheduledThreadPoolExecutor

    通常使用工厂类Executors来创建。Executors可以创建2种类型的ScheduledThreadPoolExecutor。

    ScheduledThreadPoolExecutor

    ScheduledThreadPoolExecutor的执行主要分为两大部分:

    1)当调用ScheduledThreadPoolExecutor的scheduleAtFixedRate()方法或者scheduleWith-FixedDelay()方法时,会向ScheduledThreadPoolExecutor的DelayQueue添加一个实现了RunnableScheduledFutur接口的ScheduledFutureTask。

    2)线程池中的线程从DelayQueue中获取ScheduledFutureTask,然后执行任务。

    SingleThreadScheduledExecutor

    DelayQueue封装了一个PriorityQueue,这个PriorityQueue会对队列中的Scheduled-

    FutureTask进行排序。排序时,time小的排在前面(时间早的任务将被先执行)。如果两个ScheduledFutureTask的time相同,就比较sequenceNumber,sequenceNumber小的排在前面(也就是说,如果两个任务的执行时间相同,那么先提交的任务将被先执行)。

     

    Future接口

    Future接口和实现Future接口的FutureTask类用来表示异步计算的结果。

    当我们把Runnable接口或Callable接口的实现类提交(submit)给ThreadPoolExecutor或

    ScheduledThreadPoolExecutor时,ThreadPoolExecutor或ScheduledThreadPoolExecutor会向我们返回一个FutureTask对象。

     

    (4)Runnable接口和Callable接口

    Runnable接口和Callable接口的实现类,都可以被ThreadPoolExecutor或Scheduled-

    ThreadPoolExecutor执行。它们之间的区别是Runnable不会返回结果,而Callable可以返回结果。

    除了可以自己创建实现Callable接口的对象外,还可以使用工厂类Executors来把一个

    Runnable包装成一个Callable。

    FutureTask三种状态

    1) 未启动

    2) 已启动

    3) 已完成

    Cancel

    get

    未启动

    不执行

    阻塞到完成

    已启动

    (true)中断 false(无影响)

    阻塞到完成

    已完成

    返回false

    立即返回

  • 相关阅读:
    072孤荷凌寒从零开始学区块链第72天DAPP027
    014自学方法论_养成随手记录自学过程遇到问题的好习惯
    015把注意力放在养大我们金鹅身上
    071孤荷凌寒从零开始学区块链第71天DAPP026
    070孤荷凌寒从零开始学区块链第70天DAPP024
    068孤荷凌寒从零开始学区块链第68天DAPP022
    014什么才是一个人最宝贵的资产
    013自学方法论_怎样才是最高效率加强记忆的自学
    012自学方法谈_不要依赖视频,培养自己的阅读理解能力
    013学会建立一个个自动化的管道
  • 原文地址:https://www.cnblogs.com/mercuryji/p/multithreading_executor.html
Copyright © 2011-2022 走看看