• 并发编程--线程池


    1. 使用线程池的好处

    1)降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。

    2)提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。

    3)提高线程的可管理性。线程是稀缺资源,如果无限制地创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一分配、调优和监控。

    2. 创建线程池

    Executors 工具类提供了四种不同的线程池来帮助我们创建不同需求的线程池:

    newCachedThreadPool:创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程

    newFixedThreadPool:创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待

    newScheduledThreadPool:创建一个定长线程池,支持定时及周期性任务执行

    newSingleThreadExecutor:创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行

    3. ThreadPoolExecutor

    ThreadPoolExecutor构造函数中有以下几个参数:

    corePoolSize:核心线程数,即在该线程池中运行的线程池个数。
    maximumPoolSize:线程池最大线程数,即线程池最多可以创建的线程个数。
    keepAliveTime:非核心线程的存活时间。
    unit:keepAliveTime的单位,有7种取值。TimeUnit.DAYS、TimeUnit.HOURS、TimeUnit.MINUTES、TimeUnit.SECONDS、TimeUnit.MILLISECONDS、TimeUnit.MICROSECONDS、TimeUnit.NANOSECONDS。
    workQueue:任务超过核心线程数后,被放置的阻塞队列。例如LinkedBlockingQueue。
    threadFactory:线程工厂,用来创建线程。
    handler:饱和策略,当阻塞队列已满,并且线程数已达到最大线程数时,会对新任务采取的策略。

    4. 线程池处理流程

    提交任务后,线程池先判断线程数是否达到了核心线程数(corePoolSize)。

    如果未达到线程数,则创建核心线程处理任务;否则,就执行下一步;

    然后线程池判断缓存队列是否满了。如果没满,则将任务添加到缓存队列中;否则,执行下一步;

    然后因为缓存队列满了,线程池就判断线程数是否达到了最大线程数。如果未达到,则创建非核心线程处理任务;否则,就执行饱和策略,默认会抛出RejectedExecutionException异常

     

    饱和策略(RejectedExecutionHandler):

    当任务队列和线程池都满了时所采取的应对策略,默认是AbordPolicy,表示无法处理新任务,并抛出RejectedExecutionException异常。此外还有3种策略:

    1)CallerRunsPolicy:用调用者所在的线程处理任务。此策略提供简单的反馈机制,能够减缓新任务的提交速度。

    2)DiscardPolicy:不能执行任务,并将任务删除。

    3)DiscardOldestPolicy:丢弃队列最近的任务,并执行当前的任务。

    5. 合理配置线程池

    CPU密集:指该任务要进行大量的运算操作,没有阻塞,CPU要保持全速运行;该种任务可以少配置线程数,大概和机器的cpu核数相当,这样可以使得每个线程都在执行任务

    IO密集:指该任务会要进行大量的IO操作,即大量的阻塞,由于大部分线程都阻塞,故需要多配置线程数,2*cpu核数

  • 相关阅读:
    键盘快捷键
    电脑命令行命令
    网络基础TCP/IP
    运算符优先级
    元字符汇总
    正则表达式
    模板语法(DOM与Vue数据绑定)
    computed、methods、watch
    vue实例
    坐标轴
  • 原文地址:https://www.cnblogs.com/Cryptonym/p/10671859.html
Copyright © 2020-2023  润新知