目录
一、基本概念
1.Java线程
线程是调度CPU的最小单元,也叫轻量级进程LWP(Light weight Processs)
2.线程模型
2.1.用户级线程(ULT)
用户程序实现,不依赖操作系统核心,应用提供创建、同步、调度和管理线程的函数来控制用户线程。
不需要用户态/核心态切换,速度快。内核对ULT无感知,线程阻塞则进程(包括他的所有线程)阻塞。
2.2.内核级线程(KLT)
系统内核管理线程,内核保存线程的状态和上下文信息,线程阻塞不会引起进程阻塞。在多处理系统上,多线程在多处理器上并行运行。线的创建、调度和管理由内核完成,效率比用户级线程慢,比进程操作快。
2.3.JVM虚拟机使用线程模型
内核级线程模型(KLT)
3.java线程与系统内核线程
java线程创建是依赖于系统内核,通过JVM调用系统库创建内核线程,内核线程与JAVA-Thread是1:1的映射关系。线程是我们程序运行的载体。
二、线程池概念
线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。线程池线程都是后台线程。每个线程都使用默认的堆栈大小,以默认的优先级运行,并处于多线程单元中。如果某个线程在托管代码中空闲(如正在等待某个事件),则线程池将插入另一个辅助线程来使所有处理器保持繁忙。如果所有线程池线程都始终保持繁忙,但队列中包含挂起的工作,则线程池将在一段时间后创建另一个辅助线程但线程的数目永远不会超过最大值。超过最大值的线程可以排队,但他们要等到其他线程完成后才启动。
三、线程池的意义
意义:
1. 降低资源消耗:通过重复利用已创建的线程降低线程创建、销毁线程造成的消耗;
2. 提高响应速度:当任务到达时,任务可以不需要等到线程创建就能立即执行;
3. 提高线程的可管理性:线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配、调优和监控;
使用场景:
1.单个任务处理时间比较短;
2.需要处理的任务数量较大;
四、常见线程池种类
1、newCachedThreadPool(),它是用来处理大量短时间工作任务的线程池,具有几个鲜明特点:它会试图缓存线程并重用,当无缓存线程可用时,就会创建新的工作线程;如果线程闲置时间超过60秒,则被终止并移除缓存;长时间闲置时,这种线程池,不会消耗什么资源。其内部使用SynchronousQueue作为工作队列。
2、newFixedThreadPool(int nThreads),重用指定数目(nThreads)的线程,其背后使用的是无界的工作队列,任何时候最多有nThreads个工作线程是活动的。这意味着,如果任务数量超过了活动线程数目,将在工作队列中等待空闲线程出现;如果工作线程退出,将会有新的工作线程被创建,以补足指定数目nThreads。
3、newSingleThreadExecutor(),它的特点在于工作线程数目限制为1,操作一个无界的工作队列,所以它保证了所有的任务都是被顺序执行,最多会有一个任务处于活动状态,并且不予许使用者改动线程池实例,因此可以避免改变线程数目。
4、newSingleThreadScheduledExecutor()和newScheduledThreadPool(int corePoolSize),创建的是个ScheduledExecutorService,可以进行定时或周期性的工作调度,区别在于单一工作线程还是多个工作线程。
5、newWorkStealingPool(int parallelism),这是一个经常被人忽略的线程池,Java 8 才加入这个创建方法,其内部会构建ForkJoinPool,利用Work-Stealing算法,并行地处理任务,不保证处理顺序。
五、线程池参数
1、corePoolSize:核心线程数,指定了线程池中的核心线程的个数,核心线程就是永远不会被销毁的线程,一旦被创建出来就将永远存活在线程池之中
2、maximumPoolSize:最大线程数, 指定了线程池能够创建的最大线程数量。
3、keepAliveTime: 是用于控制非核心线程最长空闲等待时间,如果一个非核心线程处理完任务后回到线程池待命,超过这个指定时长依然没有新任务的分配将导致线程被销毁。
4、unit:非核心线程池空闲时间单位。
5、workQueue:任务队列, 用来存放没有处理的任务,提供一种缓冲机制,实现这种结构的方法有很多,常使用队列,主要运用先进先出的原理。
6、threadFactory:线程工厂(线程池创建线程时候会使用定义的线程工厂产生线程)。
7、handler:拒绝策略, 当线程池的任务缓存队列已满并且线程池中的线程数目达到maximumPoolSize时,如果还有任务到来就会采取任务拒绝策略,通常有以下四种策略:
- ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。
- ThreadPoolExecutor.DiscardPolicy:丢弃任务,但是不抛出异常。
- ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新提交被拒绝的任务
- ThreadPoolExecutor.CallerRunsPolicy:由调用线程(提交任务的线程)处理该任务
六、线程池流程
1、创建一个线程池,在还没有提交任务时候,核心线程数是0,也可以调用方法初始化线程池。
2、线程池里工作线程数或者空闲线程数小于核心线程数时候,有任务提交时候会通过线程工厂创建一个工作线程执行任务。
3、线程池里空闲线程数等于核心线程数时候,有任务提交时候会把任务放入任务队列中,等待有工作线程空闲时候会获取任务队列中任务执行。
4、线程池里空闲线程数等于核心线程数时候,并且任务队列也满的时候,有任务提交时候会,判断非核心线程池数是否达到最大值,如果没有达到最大值则通过线程工厂创建非核心线程执行任务,非核心线程执行完任务空闲时候,会去任务队列中获取任务执行,当任务队列中没有任务,并且也没有新任务提交,当非核心线程会到超时时间时候销毁非核心线程。
5、线程池里空闲线程数等于核心线程数时候,并且任务队列也满的时候,并且非核心数也达到最大值时候,
有任务提交时候会执行拒绝策略,默认拒绝策略是抛出异常。