线程复用:线程池

线程复用:线程池

为了避免系统频繁地创建和销毁线程,我们可以让创建的线程进行复用。线程池中,总有几个活跃线程。当你需要使用线程时,可以从池中随便获取一个空闲线程,当工作完成时,线程不会关闭而是退回池中。

  • JDK 提供的线程池工厂方法

    • newFixedThreadPool

      返回固定线程数量的线程池。

      当有一个新的任务提交时,线程池若有空闲线程,则立即执行。若没有,则新的任务会被暂存到一个任务队列中,待线程空闲时,便处理在任务队列中的任务。

    • newSingleThreadExecutor

      返回只有一个线程的线程池。

      若多余一个任务被提及,则保存到任务队列中,线程空闲时按照先入先出的顺序执行任务。

    • newCachedThreadPool

      返回一个可根据实际情况调整线程数量的线程池。

      线程池的线程数量不确定,但若有空闲线程可以复用,则会有限使用可复用的线程。若所有线程均在工作,又有新任务提交,则创建新的线程处理任务。当所有线程在任务执行完之后,将返回线程池进行复用。

    • newSingleThreadScheduledExecutor

      返回一个 ScheduledExecutorService 对象,线程池大小为1。

      ScheduledExecutorService 接口在 ExecutorService 接口之上扩展了给定时间执行某任务的功能。

    • newScheduledThreadPool

      返回指定线程数量的 ScheduledExecutorService 对象。

  • 线程池的内部实现

    JDK 提供的线程池工厂方法实质就是 ThreadPoolExecutor 的不同参数的不同实现

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

    corePoolSize : 指定线程池中的线程数量。

    maximumPoolSize :指定线程池中的最大线程数量。

    keepAliveTime :超过corePoolSize的空闲线程,在多长时间内,会被销毁。

    unit :keepAliveTime的单位。

    workQueue :提交但未执行的任务队列。

    • 直接提交的队列

      该功能由 SynchronousQueue 对象提供,提交的任务不会被保存,而是直接提交给线程执行,如果没有空闲的线程,则尝试创建新的线程,如果已达到最大值则执行拒绝策略。

    • 有界的任务队列

      ArrayblockingQueue 实现, ArrayblockingQueue 的构造函数需要带一个容量参数(队列最大容量)。当有新的任务时,如果线程池实际线程数小于 corePoolSize ,则优先创新新的线程,如果大于 corePoolSize ,则将任务加入等待队列。

      若等待队列已满,则在总线程数不大于 maximumPoolSize 的前提下创建新的线程执行任务,否则则执行拒绝策略。因为需要等待队列满才会创建超出 corePoolSize 的线程,所以除非系统特别繁忙,否则核心线程数一般维持在 corePoolSize

    • 无界的任务队列

      LinkedBlockingQueue 实现,和有界的任务队列类似,只是等待队列会一直扩张,如果任务的创建速度一直高于处理速度,则无界队列会一直增长,直至耗尽内存。

    • 优先任务队列

      PriorityBlockingQueue 实现,是一个特殊的无界队列,会按照任务自身的优先级顺序先后执行。

    threadFactory :线程工厂,用于创建线程,一般默认。

    handler :拒绝策略。当任务太多时如何拒绝任务。

    • AbortPolicy 策略

      直接抛出异常,阻止系统正常工作。

    • CallerRunsPolicy 策略

      只要线程池未关闭,该策略直接在调用者线程中,运行当前被丢弃的任务。这样做不会真的丢弃任务,但是任务提交的线程性能可能会急剧下降。

    • DiscardPolicy 策略

      丢弃最老的一个请求(即将被执行的下一个任务),并尝试再次提交当前任务。

    • DiscardOldestPolicy 策略

      直接丢弃无法处理的任务,不做任何处理。

  • 线程池的数量

    Ncpu = CPU数量

    Ucup = CPU的使用率

    W/C = 等待时间与计算时间的比率

    最优池: Nthreads=Ncpu*Ncpu*(1+W/C)

猜你喜欢

转载自blog.csdn.net/myherux/article/details/79614744