一、线程池的优点
1、线程池能够复用已经创建了的线程来执行任务,从而降低了频繁创建和销毁线程所带来的资源消耗;
2、任务创建完成时,不必等待线程的创建,能够立即执行,提高了任务响应的速度。
二、创建线程池的七大核心参数
1、corePoorSize 核心线程数
线程池中长期存活的线程数量。一般情况下,当线程处于空闲状态时也不会被销毁。
2、maximumPoorSize 最大线程数
线程池中允许创建的最大线程数量。当线程池队列满后,能够创建的最大线程数量(核心线程总数量 + 非核心线程总数量)。
3、keepAliveTime 存活时间
非核心线程的最大空闲时间。当非核心线程处于空闲状态的时长到达这个时间,就会被销毁。
4、TimeUnit 时间单位
存活时间的时间单位。
5、workQueue 线程池工作队列
存放工作任务的阻塞队列。当有任务被提交时,若没有线程能够处理,该任务就会被放到队尾,等待线程执行。
6、threadFactory 线程工厂
创建一个新的线程时,用到的线程工程。可以用来设置线程名等线程参数。
7、handler 拒绝策略
当线程池中的工作线程数量达到了最大线程数量,并且工作队列也容量也满了,此时有任务提交进来时,需要做的处理。
三、线程池的执行流程
如图,线程池的执行策略可以分为三个步骤:
1、当任务提交时,若此时的工作线程数小于核心线程数,则会创建一个线程来执行任务;
2、当核心线程数已满时,如果此时阻塞队列没有满,则将任务放入到阻塞队列中,等待线程执行;
3、若核心线程数和阻塞队列都已满时,会去判断当前线程数是否达到最大线程数,没有达到就会创建一个非核心线程来执行任务,达到就执行拒绝策略。
四、常用的四种工作队列
1、ArrayBlockingQueue 基于数组的有界阻塞队列
当核心线程数已满,会将新的任务放到队列当中,并按照FIFO的顺序等待线程调度。若队列中的任务达到给定的数值,则会启动新的线程去执行任务,若当前线程数量到达最大线程数量,则拒绝执行任务。
2、LinkedBlockingQuene 基于链表的无界阻塞队列
也是按照FIFO的,容量为Integer类型的最大值,所以近似于无界。所以maxPoolSize此时就是无效的,因为队列无界,能够不断添加任务,导致不会去创建非核心线程,线程数量最多等于核心线程数量,达不到最大线程数量。
3、SynchronousQuene 不缓存任务的阻塞队列
相当于没有队列,当当前线程数达到corePoolSize时,直接创建非核心线程执行任务,当当前线程数到达maxPoolSize后,则拒绝任务。
4、PriorityBlockingQueue 具有优先级的无界阻塞队列
默认情况下,元素采用自然顺序升序排列,也可以自定义类,然后实现compareTo()方法来指定元素排序规则。
五、常用的四种拒绝策略
1、AbortPolicy
中止策略,直接抛出 RejectedExecutionException 错误。线程池默认使用的策略。
编写一个简单的执行deno:
public static void main(String[] args) { // 创建一个线程池 ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(2, 5, 3L, TimeUnit.MINUTES, new ArrayBlockingQueue<>(1), new ThreadPoolExecutor.AbortPolicy() ); for (int i = 0; i < 100; i++) { int finalI = i; poolExecutor.execute(() -> { try { Thread.sleep(1000); System.out.println("[" + Thread.currentThread().getName() + "]:" + finalI + "同学完成"); } catch (InterruptedException e) { e.printStackTrace(); } }); } poolExecutor.shutdown(); }
执行结果:达到最大线程数后,直接抛出错误
2、CallerRunsPolicy
调用者执行策略,将任务返回给提交该任务的线程执行。
执行demo不变,将执行策略换为CallerRunsPolicy,运行结果:
可见,因为我们的main线程提交任务给线程池后,线程池队列及线程数量都已满,便将执行的任务返回给main线程,由main线程执行。
3、DiscardPolicy
丢弃策略,将该任务丢弃,且不抛出异常。
执行demo不变,将执行策略换为DiscardPolicy,运行结果:
达到最大线程数后,不执行提交的任务。
4、DiscardOldestPolicy
丢弃最老的策略,丢弃队列最前面的任务。
执行demo不变,将执行策略换为DiscardOldestPolicy,运行结果:
0~5号任务执行过程中,不断有新的任务提交,最后执行到了第99号任务,因为前面的不断被丢弃,99最后被放入队列并被线程执行。
标签:Java,策略,队列,创建,介绍,任务,线程,执行 From: https://www.cnblogs.com/hehuahua/p/17511344.html