• 线程池学习


    什么是线程池
    创建一组可供管理的线程,它关注的是如何缩短或调整线程的创建与销毁所消费时间的技术,从而提高服务器程序性能的。
    它把线程的创建与销毁分别安排在服务器程序的启动和结束的时间段或者一些空闲的时间段以减少服务请求是去创建和销毁线程的时间。
    它还显著减少了创建线程的数目。

    为什么要使用线程池
    当我们在使用线程时,如果每次需要一个线程时都去创建一个线程,这样实现起来很简单,但是会有一个问题:当并发线程数过多时,并且每个线程都是执行一个时间很短的任务就结束时,这样创建和销毁线程的时间要比花在实际处理任务的时间要长的多,在一个JVM里创建太多的线程可能会导致由于系统过度消耗内存或切换过度导致系统资源不足而导致OOM问题。 线程池为线程生命周期开销问题和资源不足问题提供了解决方案。通过对多个任务重用线程,线程创建的开销被分摊到了多个任务上。

    如何正确的使用线程池
    不要对那些同步等待其它任务结果的任务排队。这可能会导致上面所描述的那种形式的死锁,在那种死锁中,所有线程都被一些任务所占用,这些任务依次等待排队任务的结果,而这些任务又无法执行,因为没有空闲的线程可以使用。
    在为任务时间可能很长的线程使用合用的线程时要小心。如果程序必须等待诸如 I/O 完成这样的某个资源,那么请指定最长的等待时间,以及随后是失效还是将任务重新排队以便稍后执行。
    理解任务。要有效地调整线程池大小,需要理解正在排队的任务以及它们正在做什么。它们是 CPU 限制的吗?它们是 I/O 限制的吗?你的答案将影响如何调整应用程序。如果有不同的任务类,这些类有着截然不同的特征,那么为不同任务类设置多个工作队列可能会有意义,这样可以相应地调整每个池。
    ThreadPoolExecutor构造函数中几个重要参数的解释
    corePoolSize:核心池大小,即线程的数量。
    maximumPoolSize:线程池最大线程数,表示在线程池中最多能创建多少个线程。
    keepAliveTime:表示线程没有任务执行时最多保持多久时间会终止。
    unit:参数keepAliveTime的时间单位,有7种取值,具体可查看前面章节。
    workQueue:线程池采用的缓冲队列,用来存储等待执行的任务。
    threadFactory:线程工厂,主要用来创建线程。
    handler:线程的阻塞策略。当线程池中线程数量达到maximumPoolSize时,仍有任务需要创建线程来完成,则handler采取相应的策略。

    线程池的状态
    RUNNING:能接受新提交的任务,并且也能处理阻塞队列中的任务;
    SHUTDOWN:关闭状态,不再接受新提交的任务,但却可以继续处理阻塞队列中已保存的任务。在线程池处于 RUNNING 状态时,调用 shutdown()方法会使线程池进入到该状态.(finalize() 方法在执行过程中也会调用shutdown()方法进入该状态);
    STOP:不能接受新任务,也不处理队列中的任务,会中断正在处理任务的线程。在线程池处于 RUNNING 或 SHUTDOWN 状态时,调用 shutdownNow() 方法会使线程池进入到该状态;
    TIDYING:如果所有的任务都已终止了,workerCount (有效线程数) 为0,线程池进入该状态后会调用 terminated() 方法进入TERMINATED 状态。
    TERMINATED:在terminated() 方法执行完后进入该状态,默认terminated()方法中什么也没有做。
    线程池的执行流程
    当线程数量小于corePoolSize时,任务来时会创建新的线程来处理,并把该线程加入线程队列中(实际上是一个HashSet)(此步骤需要获取全局锁,ReentryLock);
    如果当前线程数量达到了corePoolSize,任务来时将任务加入BlockingQueue;
    如果任务列队满了无法加入新的任务时,会创建新的线程(同样需要获取全局锁);
    如果线程池数量达到maximumPoolSize,并且任务队列已满,新的任务将被拒绝;

    常用的几种线程池
    CachedThreadPool: 创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
    FixedThreadPool:创建一个指定工作线程数量的线程池。每当提交一个任务就创建一个工作线程,如果工作线程数量达到线程池初始的最大数,则将提交的任务存入到阻塞队列中。
    SingleThreadExecutor:创建一个单线程化的Executor,即只创建唯一的工作者线程来执行任务,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
    ScheduleThreadPool:创建一个定长的线程池,而且支持定时的以及周期性的任务执行,支持定时及周期性任务执行。

  • 相关阅读:
    关于连接connection reset的问题
    Redis应用场景及缓存问题
    zookeeper集群及kafka集群搭建
    使用自定义注解和切面AOP实现Java程序增强
    Shell脚本控制docker容器启动顺序
    正则表达式匹配${key}并在Java中使用
    Redis基本数据结构之ZSet
    Redis基本数据结构之Set
    Redis基本数据结构之Hash
    Redis基本数据结构之List
  • 原文地址:https://www.cnblogs.com/chendezhen/p/16187008.html
Copyright © 2020-2023  润新知