线程池学习

目录

为什么引入线程池

自定义线程池

线程池的执行流程


为什么引入线程池

创建过多线程带来的问题:

  • 消耗内存资源
  • CUP的开销(上下文切换)

所以引入了线程池的概念

线程池的逻辑就是提前创建好若干个线程,放进一个容器里(HashSet),如果有任务,就把这个任务分配给线程池中的线程来执行。线程执行完任务不会销毁,而是就是等待任务的分配。

线程池的好处

  • 避免频繁创建销毁线程带来的性能开销(复用线程)
  • 合理设置线程大小避免出现资源瓶颈(控制资源数量)

Java中提供的线程池

//固定线程数
Executors.newFixedThreadPool(3);
//单个线程
Executors.newSingleThreadExecutor();
//带缓存的
Executors.newCachedThreadPool();
//可以延期执行
Executors.newScheduledThreadPool(3);

自定义线程池

核心参数

  • corePoolSize 核心线程数
  • maximumPoolSize 最大线程数
  • keepAliveTime 临时线程的存活时间
  • unit 存活时间单位
  • workQueue 阻塞队列
  • threadFactory 创建线程的线程工厂
  • handler 拒绝策略
public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler)

拒绝策略

  • AbortPolicy 抛出异常
  • CallerRunsPolicy 直接调用线程的run方法
  • DiscardOldestPolicy 把阻塞队列中的的任务poll,然后再把添加的任务excutor
  • DiscardPolicy 不做任何处理
  • 自定义拒绝策略,继承RejectedExecutionHandler重写他的方法

如何设置线程池的大小

  • CPU密集型(大量的使用CPU资源) ->保持和CUP核心数一致(减少上下文切换)
  • IO密集型(大量的IO处理) -> 可以根据实际情况多设置一些

继承线程池重写他的before和after方法可以对任务进行监控

execute和submit的区别

execute无返回值

submit有返回值Future

线程池的执行流程

        通过excutor执行任务,首先会判断当前线程是否小于核心线程数,如果小于就会创建个Woker,然后放进hashSet容器进行存储。然后调用woker.star来启动线程。线程会调用任务的run方法来执行业务逻辑,,执行完一个,线程会自旋的去阻塞队列中take阻塞式的拿任务并执行。如果阻塞队列放满了,会判断当前线程是否小于最大线程数,如果小于就会继续创建woker线程,如果已经大于最大线程数了,就会执行拒绝策略。我们可以通过继承拒绝策略的类来自定义拒绝策略。

图解

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

w7486

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值