线程池使用

文章目录

  • 前言
  • 一、为什么要用线程池?
  • 二、线程池的原理
  • 三、线程池api
  • 总结


前言

线程池的分析


一、为什么要用线程池?

1、线程在java中是一个对象,更不是操作系统的资源,线程创建、销毁都需要时间。如果创建时间+销毁时间>执行任务的时间就非常不划算。

2、java对象占用堆内存,操作系统线程占用系统内存,根据jvm规范,一个线程默认最大栈大小1M,这个栈空间是需要从系统内存中分配的。线程过多会很消耗内存(操作系统频繁的切换线程也会影响性能)。

线程池的推出,就是为了方便控制线程的数量。

二、线程池的原理(概念)

概念:

1、线程池管理器:用于创建并管理线程池,包括创建线程池、销毁线程池,添加新任务。

2、工作线程:线程池中线程,在没有任务时处于等待状态,可以循环的执行任务;

3、任务接口:每个任务必须实现的接口,供工作线程调度任务的执行,主要规定了任务的入口,任务执行完后的收尾工作,任务的执行状态等;

4、任务队列:用于存放没有处理的任务,提供一种缓冲机制。

线程池原理-任务excutor过程

 核心线程数量、最大线程数量、队列大小的关系;

1、是否达到核心线程数量?没达到,创建新的线程来执行;

2、工作队列是否已满? 没满,将新提交的任务存储到工作队列中;

3、是否达到线程池最大数量?没达到,创建新的线程来执行,直到到达线程池最大数量

4、最后执行拒绝策略来处理这个任务(到达线程池最大数量后的线程,程序会拒绝执行)

线程池使用_第1张图片

三、线程池API使用示例

线程池使用_第2张图片


1、ThreadPoolExecutor标准线程池实现的使用方式

1、线程池信息: 核心线程数量5,最大数量10,无界队列,超出核心线程数量的线程存活时间:5秒, 指定拒绝策略的
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 10, 5, TimeUnit.SECONDS, new LinkedBlockingQueue());
结果:线程池线程数量为:5,超出数量的任务,其他的进入队列中等待被执行
2、 线程池信息: 核心线程数量5,最大数量10,队列大小3(也就是最大容纳13个任务),超出核心线程数量的线程存活时间:5秒, 指定拒绝策略的.
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 10, 5, TimeUnit.SECONDS,
      new LinkedBlockingQueue(3), new RejectedExecutionHandler() {
         @Override
         public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
            System.err.println("有任务被拒绝执行了");
         }
      });
 预计结果: 5个任务直接分配线程开始执行;3个任务进入等待队列,队列不够用;临时加开5个线程来执行任务(5秒没活干就销毁);队列和线程池都满了,剩下2个任务,没资源了,被拒绝执行;任务执行,5秒后,如果无任务可执行,销毁临时创建的5个线程。
3、 线程池信息: 核心线程数量5,最大数量5,无界队列,超出核心线程数量的线程存活时间:5秒
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 5, 0L,TimeUnit.MILLISECONDS,new LinkedBlockingQueue());
预计结果:线程池线程数量为:5,超出数量的任务,其他的进入队列中等待被执行

 2、ScheduledThreadPoolExecutor实现类的使用

ScheduledThreadPoolExecutor threadPoolExecutor = new ScheduledThreadPoolExecutor(5);
		// 周期性执行某一个任务,线程池提供了两种调度方式,这里单独演示一下。测试场景一样。
		// 测试场景:提交的任务需要3秒才能执行完毕。看两种不同调度方式的区别
		// 效果1: 提交后,2秒后开始第一次执行,之后每间隔1秒,固定执行一次(如果发现上次执行还未完毕,则等待完毕,完毕后立刻执行)。
		// 也就是说这个代码中是,3秒钟执行一次(计算方式:每次执行三秒,间隔时间1秒,执行结束后马上开始下一次执行,无需等待)
		threadPoolExecutor.scheduleAtFixedRate(new Runnable() {
			@Override
			public void run() {
				try {
					Thread.sleep(3000L);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println("任务-1 被执行,现在时间:" + System.currentTimeMillis());
			}
		}, 2000, 1000, TimeUnit.MILLISECONDS);

		// 效果2:提交后,2秒后开始第一次执行,之后每间隔1秒,固定执行一次(如果发现上次执行还未完毕,则等待完毕,等上一次执行完毕后再开始计时,等待1秒)。
		// 也就是说这个代码钟的效果看到的是:4秒执行一次。 (计算方式:每次执行3秒,间隔时间1秒,执行完以后再等待1秒,所以是 3+1)
		threadPoolExecutor.scheduleWithFixedDelay(new Runnable() {
			@Override
			public void run() {
				try {
					Thread.sleep(3000L);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println("任务-2 被执行,现在时间:" + System.currentTimeMillis());
			}
		}, 2000, 1000, TimeUnit.MILLISECONDS);

你可能感兴趣的:(java)