线程池的应用及核心原理详解

线程池是什么

线程池是值提前创建好若干的线程,让有任务需要处理时,就会分配线程池中的线程去执行这些任务,让任务在执行完成后也不会销毁这个线程,而是会由线程池进行管理,继续等待下一任务提交到线程池。由于创建和销毁线程池都是消耗系统资源的,所以有业务需要频繁的创建线程时,就可以使用线程池来管理这些线程。

使用线程池的好处

1:降低系统资源消耗,通过重复利用已创建的线程执行任务,降低频繁创建销毁线程造成的资源消耗。

2:提高系统的响应速度,当有任务提交到线程池时可以直接分配线程执行,不需要再去创建线程。

3:提高线程的管理性,线程是稀缺的资源,如果无线的创建线程,不仅会造成系统资源的消耗,还会降低系统的稳定性,使用线程池来管理,可以进行统一的资源分配。

线层池使用入门

首先创建一个Runnable接口的实现类

class Demo implements Runnable{

    public void run() {
        System.out.println(Thread.currentThread().getName());
    }
}

通过Executors.newFixedThreadPool方法区创建一个线程池,并制定最大线程数和核心线程数都为5

executorService.execute:提交任务到线程池

在通过线程池去执行这个任务

public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(5);
        executorService.execute(new Demo());
        System.out.println("end ==> "+ Thread.currentThread().getName());
}

输出

end ==> main
pool-1-thread-1

Executor

通过Executors提供了四种创建线程池的方式:

newCachedThreadPool:创建一个线程池,可允许同时运行线程的最大数量为Integer.MAX_VALUE,在60秒内没有新的任务提交到线程池,则这些线程会被回收。

newFixedThreadPool :创建一个定长线程池,可控制线程最大并发数,当提交的任务数超过了最大线程数后会将任务都放在队列中等待。

newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。

newSingleThreadExecutor 创建一个单线程的线程池,它只会用唯一的工作线程来执行任务,会保证所有任务按照指定顺序提交的顺序执行。

ThreadPoolExecutor

核心参数

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler)

corePoolSize:核心的线程数,定义了最小可以同时运行的线程数量。

maximumPoolSize:最大线程数,当队列中存放的任务达到队列的最大容量时,会继续创建线程至最大线程数。

keepAliveTime & unit:当线程池中的线程数大于了核心线程数时,这些多余的线程所存活的最长时间,unit为这个时间的单位。

workQueue:用来存放任务的队列,提交到线程池中的任务会先提交到队列中。

threadFactory:用来创建线程的工厂,通常设置为默认的

handler:用来定义当池中的线程到达了最大线程数,并且队列存放满了后,用来处理继续提交到线程池中任务的策略。

拒绝策略

四种默认的拒绝策略:

AbortPolicy:直接抛出一个RejectedExecutionException类型的RuntimeException异常,通知用户任务呗拒绝了

DiscardPolicy:直接丢弃提交到线程池的任务。

DiscardOldestPolicy:丢弃最早进入队列的任务

CallerRunsPolicy:将任务交给将任务提交到线程池的线程执行

自定义拒绝策略

实现RejectedExecutionHandler接口,并重写rejectedExecution方法,在方法内自定义拒绝处理逻辑

@Slf4j
class CustomRejectedExecutionHandler implements RejectedExecutionHandler {

    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        log.info("====拒绝策略====");
    }
}

线程池的工作原理

首先在创建线程池的时候,池内是没有线程的,当用户提交任务到了线程池后,会先将任务提交到队列中,这时会创建一个线程来从队列中取出这个任务并执行,当这个线程执行完任务后,会回来继续监听队列,当再有任务提交到线程池时,会先判断当前池内的线程数是否到达了核心线程数,如果到了核心线程数,就不在继续创建线程,而是使用之前创建的空闲状态的线程执行。如果未达到核心线程数,则会继续创建线程来执行任务,直到创建的线程数到达了设置的核心线程数,这时所创建的线程都会监听队列,当有任务提交到了队列后,线程会将任务取出执行。如果没有任务提交到队列,则所有的线程都阻塞到队列上。

在到达了设置的corePoolSize后,继续提交到线程的任务会直接进入队列中,当提交的任务将将队列填满后,继续提交的任务会创建临时线程来执行,临时线程与核心线程相同,在执行完任务后同样也会监听队列。当临时线程监听队列时间超过设置的keepAliveTime 设置的时间后会将其销毁。但是如果池内的线程数到达了maximumPoolSize设置的线程数后,则不会在继续创建新的线程,这时如果再有任务提交到线程池,则会触发拒绝策略,根据制定的拒绝策略来处理提交的任务

在这里插入图片描述

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值