我是靠谱客的博主 懦弱荷花,这篇文章主要介绍ThreadPoolExecutor基本介绍+简单案例,现在分享给大家,希望可以做个参考。

文章目录

    • 前言
    • 一、构造函数
    • 二、参数解释
    • 三、案例分析


前言

在实际开发中,线程池的创建不能使用Exectors去创建线程池,而是采用最原始的ThreadPoolExecutor来创建线程池,这样可以让编写人员更加明确线程池的运行规则,避免不必要的错误。下面我们就来看看ThreadPoolExecutor的构造参数以及它们的作用。


一、构造函数

ThreadPoolExecutor一共有四种有参构造,下面只给出参数最全的构造函数

复制代码
1
2
3
4
5
6
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)

二、参数解释

  • corePoolSize:即使空闲时仍保留在池中的线程数(核心线程数)
  • maximumPoolSize:池中允许的最大线程数(核心线程数+救急线程数)
    注:救急线程是在任务数大于核心线程数时创建的线程,用于救急,用完以后过指定时间自动销毁
  • keepAliveTime:当线程数大于内核时,这是多余的空闲线程在终止前等待新任务的最大时间。
  • unit:keepAliveTime参数的时间单位
  • workQueue:用于在执行任务之前使用的队列。 这个队列将仅保存execute方法提交的Runnable任务。
  • threadFactory:执行程序创建新线程时使用的工厂
  • handler:达到线程限制和队列容量时,执行的拒绝策略

三、案例分析

  • 自定义Runnable实现类
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
class MyRunnable implements Runnable { @Override public void run() { try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } } }
  • 构造函数
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/* 默认开启1个线程,最大可开启3个线程, 当救急线程等待新任务超过1秒后没被使用就会销毁救急线程, 允许2个任务进入LinkedBlockingDeque阻塞队列等待, 用了Executors对象提供的默认线程创建工厂, AbortPolicy表示拒绝任务的处理程序。 */ ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( 1, 3, 1, TimeUnit.SECONDS, new LinkedBlockingDeque<>(2), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy()); }
  • 相关介绍:

    • LinkedBlockingDeque:是双向链表实现的双向并发阻塞队列。该阻塞队列同时支持FIFO和FILO两种操作方式,即可以从队列的头和尾同时操作(插入/删除);并且,该阻塞队列是支持线程安全。
    • AbortPolicy: 线程池的默认拒绝策略,即丢弃任务并抛出RejectedExecutionException异常。
      注:一共有4种基本的拒绝策略,这里采用默认的进行简单的案例讲解。
  • 代码1

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
for (int i = 0; i <7 ; i++) { Thread thread = new Thread(new MyRunnable()); threadPoolExecutor.execute(thread); System.out.println( "当前核心线程数:"+threadPoolExecutor.getCorePoolSize() +" 当前池中线程数:"+threadPoolExecutor.getPoolSize() +" 当前阻塞队列任务数:"+threadPoolExecutor.getQueue().size()); } threadPoolExecutor.shutdown(); /* 执行结果: 当前核心线程数:1 当前池中线程数:1 当前阻塞队列任务数:0 当前核心线程数:1 当前池中线程数:1 当前阻塞队列任务数:1 当前核心线程数:1 当前池中线程数:1 当前阻塞队列任务数:1 当前核心线程数:1 当前池中线程数:1 当前阻塞队列任务数:2 当前核心线程数:1 当前池中线程数:2 当前阻塞队列任务数:2 当前核心线程数:1 当前池中线程数:3 当前阻塞队列任务数:2 Exception in thread "main"java.util.concurrent.RejectedExecutionException */
  • 分析1
复制代码
1
2
3
4
5
6
7
8
第一个任务到来时,线程池为空,直接创建核心线程来处理任务 第二个任务到来时,因为核心线程已满,则将该任务放入阻塞队列中 第三个任务到来时,第一个任务执行完毕,取出阻塞队列中的第二个任务来执行,将第三个任务加入阻塞队列 第四个任务到来时,因为第二个任务未执行完毕,因此加入阻塞队列中 第五个任务到来时,因为阻塞队列已满,则创建救急线程来执行第三个任务,将第五个任务加入阻塞队列 第六个任务到来时,因为阻塞队列已满,则创建救急线程来执行第四个任务,将第六个任务加入阻塞队列 第七个任务到来时,因为阻塞队列已满并且最大线程数已满,则新任务无法处理,调用AbortPolicy处理,抛异常
  • 代码2
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
for (int i = 0; i <6 ; i++) { Thread thread = new Thread(new MyRunnable()); threadPoolExecutor.execute(thread); System.out.println( "当前核心线程数:"+threadPoolExecutor.getCorePoolSize() +" 当前池中线程数:"+threadPoolExecutor.getPoolSize() +" 当前阻塞队列任务数:"+threadPoolExecutor.getQueue().size()); } Thread.sleep(2000); System.out.println( "当前核心线程数:"+threadPoolExecutor.getCorePoolSize() +" 当前池中线程数:"+threadPoolExecutor.getPoolSize() +" 当前阻塞队列任务数:"+threadPoolExecutor.getQueue().size()); threadPoolExecutor.shutdown(); /* 执行结果: 当前核心线程数:1 当前池中线程数:1 当前阻塞队列任务数:0 当前核心线程数:1 当前池中线程数:1 当前阻塞队列任务数:1 当前核心线程数:1 当前池中线程数:1 当前阻塞队列任务数:1 当前核心线程数:1 当前池中线程数:1 当前阻塞队列任务数:2 当前核心线程数:1 当前池中线程数:2 当前阻塞队列任务数:2 当前核心线程数:1 当前池中线程数:3 当前阻塞队列任务数:2 当前核心线程数:1 当前池中线程数:1 当前阻塞队列任务数:0 */
  • 分析2
复制代码
1
2
3
4
5
前六行结果同上 第七行结果:由于此时线程任务执行完后,睡了2秒, 此时由于两个救急线程完成任务后1秒没有新任务,则救急线程销毁 线程池中只剩下核心线程

最后

以上就是懦弱荷花最近收集整理的关于ThreadPoolExecutor基本介绍+简单案例的全部内容,更多相关ThreadPoolExecutor基本介绍+简单案例内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(66)

评论列表共有 0 条评论

立即
投稿
返回
顶部