java线程池

为什么要使用线程池?

在实际的业务中,有很多场景需要用到多线程,比如,

  1. 数据库插入100W数据或者通过接口获取100W数据,
  2. 导出100W数据excel表

解决方案:

  1. 在1场景中,如果开启线程去处理,每个线程处理5W条,那么要开启20个线程。
  2. 在场景2中,因为处理时间不确定,如果采用同步的方式,最终导致链接超时。那么考虑开启线程处理。等excel生成好后,再发起请求下载。

使用以下创建线程方式

new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println("5万条数据入库!");
    }
}).start();

问题:
由于插入数据库的时间较久,不能很快的处理,这样的话,一段时间之后,系统中就会有很多的这种插入数据的线程,最终资源耗尽。疯狂引发GC,最终服务无法对外提供服务。

虽然多线程技术可以充分发挥多核处理器的计算能力,提高生产系统的吞吐量和性能。但是,若不加控制和管理的随意使用线程,对系统的性能反而会产生不利的影响。

如果我们使用线程池的方式的话,可以合理指定线程的数量,超过数量的线程只需要排队等待线程池的线程即可,不会出现线程池过多而消耗系统资源的情况。

线程生命周期

什么是线程池?

本质上只是对线程进行管理的逻辑。

使用线程池的好处

  1. 降低资源消耗。(免去频繁创建线程资源占用)
  2. 提高响应速度。(免去频繁创建线程时间)
  3. 对线程进行管理。

JDK线程池实现

ThreadPoolExecutor
ExecutorService 接口如下:
在这里插入图片描述
Executors
在这里插入图片描述
其中常用几类如下:

	public static ExecutorService newFixedThreadPool()
	public static ExecutorService newSingleThreadExecutor()
	public static ExecutorService newCachedThreadPool()
	public static ScheduledExecutorService newSingleThreadScheduledExecutor()
	public static ScheduledExecutorService newScheduledThreadPool()
  1. newFixedThreadPool:该方法返回一个固定线程数量的线程池;
  2. newSingleThreadExecutor:该方法返回一个只有一个现成的线程池;
  3. newCachedThreadPool:返回一个可以根据实际情况调整线程数量的线程池;
  4. newSingleThreadScheduledExecutor:该方法和newSingleThreadExecutor的区别是给定了时间执行某任务的功能,可以进行定时执行等;
  5. newScheduledThreadPool:在4的基础上可以指定线程数量。

查看: newFixedThreadPool
在这里插入图片描述
查看: newCachedThreadPoo
在这里插入图片描述
结论: 类似的其他方法一样,在Executors内部创建线程池的时候,实际创建的都是一个ThreadPoolExecutor对象,只是对ThreadPoolExecutor构造方法,进行了默认值的设定。

ThreadPoolExecutor的构造方法如下:
在这里插入图片描述
参数说明:

  1. corePoolSize 保留的最小线程数,他们不会消失,除非设置了allowCoreThreadTimeOut。
  2. maximumPoolSize 池中允许存在的最大线程。
  3. keepAliveTime 除了核心线程之外的多余线程,空闲超过这个时间就会被回收。
  4. unit keepAliveTime的时间单位
  5. workQueue 线程队列实现类
  6. threadFactory 线程工厂实现类
  7. handler 当线程被阻塞时的处理方法

以下条件触发异常:IllegalArgumentException
corePoolSize < 0
keepAliveTime < 0
maximumPoolSize <= 0
maximumPoolSize < corePoolSize

workQueue 常用三个实现类

  1. ArrayBlockingQueue (有界队列,可迭代)
    数组队列:一旦创建,容量不能改变,有序,按照加入顺序执行,当队列满了,线程将被阻塞
  2. LinkedBlockingQueue (无界队列,可迭代)
    链式队列:比基于数组的队列具有更高的吞吐量,可预测性较差,在每次插入时动态创建,会导致排队超过内存容量,除非指定大小
  3. SynchronousQueue (同步队列)
    队列中只能有一个任务在执行,其他任务将阻塞。

如何创建?

new ThreadPoolExecutor(1, 1, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<>(1),Executors.defaultThreadFactory());

异常处理

默认 RejectedExecutionHandler 实现 是AbortPolicy 类 ,该策略会抛出异常,并丢弃当前任务。
在这里插入图片描述
在这里插入图片描述
在代码中catch 即可。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值