vps 网站异常,二次开发公司,怎么修改wordpress主题字体,网站突然暴增流量这篇文章我们来讲一下线程池的相关内容
目录
1.什么是线程池
1.1为什么要用线程池
1.2线程池的优势
2.线程池的使用
3.线程池的关闭
4.线程池中的execute和submit方法的一些区别
5.线程池的参数和原理
6.自定义线程池
7.总结 1.什么是线程池
1.1为什么要用线程池
首…这篇文章我们来讲一下线程池的相关内容
目录
1.什么是线程池
1.1为什么要用线程池
1.2线程池的优势
2.线程池的使用
3.线程池的关闭
4.线程池中的execute和submit方法的一些区别
5.线程池的参数和原理
6.自定义线程池
7.总结 1.什么是线程池
1.1为什么要用线程池
首先我们要清楚这样的一个问题我们为什么要用线程池
思考下面的这样的一个场景某线上商城做秒杀活动1秒内有10万个请求打来我们的服务器能在1秒内创建10万个线程吗显然是不合理的。其次我们使用线程时会伴随着线程的创建和消耗当线程数量很多时这会占用机器的资源所以这也不合理。为了解决上面提到的问题所以我们使用了线程池。
如果并发的线程数量很多并且每个线程都是执行一个时间很短的任务就结束了这样频繁创建线程就会大大降低系统的效率因为频繁创建线程和销毁线程需要时间。
那么有没有一种办法使得线程可以复用就是执行完一个任务并不被销毁而是可以继续执行其他的任务在Java中可以通过线程池来达到这样的效果。
线程池其实就是一个容纳多个线程的容器其中的线程可以反复使用省去了频繁创建线程对象的操作无需反复创建线程而消耗过多资源。
1.2线程池的优势
线程池做的工作主要是控制运行的线程数量处理过程中将任务放入队列然后在线程创建后启动这些任务如果线程数量超过了最大数量超出数量的线程排队等候等其他线程执行完毕再从队列中取出任务来执行。
它的主要特点为线程复用控制最大并发数管理线程。
线程池的优势
第一降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的销耗。第二提高响应速度。当任务到达时任务可以不需要等待线程创建就能立即执行。第三提高线程的可管理性。线程是稀缺资源如果无限制的创建不仅会销耗系统资源还会降低系统的稳定性使用线程池可以进行统一的分配调优和监控
2.线程池的使用
对于线程池的原理不是很清楚的情况下很有可能配置的线程池不是较优的因此在java.util.concurrent . Executors 线程工厂类里面提供了一些静态工厂生成一些常用的线程池。官方建议使用 Executors工程类来创建线程池对象。Java类库提供了许多静态方法来创建一个线程池:
Executors类中创建线程池的方法如下:
a、newFixedThreadPool创建一个固定长度的线程池当到达线程最大数量时线程池的规模将不再变化。b、newCachedThreadPool创建一个可缓存的线程池如果当前线程池的规模超出了处理需求将回收空的线程当需求增加时会增加线程数量线程池规模无限制。c、newSingleThreadPoolExecutor创建一个单线程的Executor确保任务对了串行执行d、newScheduledThreadPool创建一个固定长度的线程池但是是可以定时的进行调度
下面我们就通过代码来看一下各种方法的使用 这个其实没啥好说的因为这个用的是Java中提供的线程池的工具类是很简单的直接用就行。
3.线程池的关闭
下面看一下线程池的关闭
我们创建一个线程池在使用完毕后一定要关闭线程池关闭线程池的代码要放在finally里面目的是为了避免程序出错导致线程池没有关闭。我们关闭线程池后线程池中正在执行的线程不会立刻被停止它会等到该线程执行完毕后再关闭即线程池是会等待线程池中所有的线程都被执行完才关闭。
为什么要关闭线程池为了避免线程池中的线程一直占用系统资源造成内存泄漏
下面看一下代码 注意区分shutdown和shutdownNow二者的区别
4.线程池中的execute和submit方法的一些区别
下面我们来看一下线程池中的execute方法和submit方法的区别
区别一
execute方法的入参只能是Runnable而submit方法的入参可以是Runnable也可以是Callable
下面看一下代码 区别二
execute的返回值为void类型而submit的返回值为Future类型
下面看一下代码 区别三
execute 会在子线程中抛出异常但是主线程中捕捉不到。而submit是不会立刻抛出异常它会将此异常暂时存起来如果想要将该异常抛出需要用Future对象接收submit的返回值然后调用Future的get方法。
下面看一下代码 5.线程池的参数和原理
下面我们来看一下线程池的参数和原理
首先我们看一下我们四种创建线程池的方式然后Ctrl单击看一下它的源码 我们会发现这四种创建线程池的源码基本相同都是返回了一个ThreadPoolExecutor对象区别就在于里面的参数不一样。我们再单击看一下ThreadPoolExecutor的源码
如上图所示下面我们来介绍一下ThreadPoolExecutor中参数的意思
corePoolSize核心线程数量这个不用过多解释maximumPoolSize最大线程数量就是这个线程池最大能开辟的线程数量KeepAliveTime非核心线程的空闲状态的存活时间就是如何该线程不是核心线程并且它是空闲的那么它的存活时间是多少是long类型的数字unit非核心线程的空闲状态的存活时间的单位workQueue工作队列阻塞队列threadFactory线程工程创建线程用的就是一个接口然后平时使用的就是创建默认线程handler拒绝策略就是当我们的核心线程数阻塞队列最大线程数都满了的情况的下还有线程来那么就按照这个拒绝策略进行拒绝
下面就整个流程进行一下梳理 首先我们进行提交任务然后程序会判断你提交的任务数量是否大于你创建线程池的核心线程数量如何不大于OK那么程序开始创建线程执行任务如果大于了核心线程数量那么多余的任务进入阻塞队列里面进行等待如果这时阻塞队列满了那么程序会判断你创建线程池的最大线程数量是否满了如果没满那么程序根据最大线程数量来创建线程执行任务如果这时最大线程数量也满了那么就执行拒绝策略多余的任务就被拒绝了不接受了。
这里对最大线程数量和非核心线程空闲状态存活时间进行一下场景解释 假设现在有一个促销秒杀活动比如双十一、618等。你的网站日常活跃用户只有5000万所以你的程序的核心线程数设置为5000万然后最大线程数设置为7000万但是在活动促销的那两个小时你的网站的活跃用户达到了1亿那么你就不可能再把最大线程数设置为7000万了而是设置为1亿但是你只有那两个小时的用户活跃数是1亿所以你不可能一直让那1亿个线程开着所以你将非核心线程的空闲存活时间设置为2h时间一过如果该非核心线程是空闲状态那么该线程就被销毁这样就可以节约资源了。
下面看一下拒绝策略 这个了解一下就可以了。
6.自定义线程池
上面我们学习了线程池的核心源码和其中的一些参数的含义下面我们来书写一个自定义的线程池然后我们再来具体的分析一下
代码如下
然后我们来看一下输出结果 下面再用一张图来解释一下吧
其实这是很好理解的
7.总结
这篇文章我们主要介绍了一下线程池的相关内容包括什么是线程池怎么创建或者说怎么使用线程池线程池的注意点线程池中两个方法的区别以及如何自定义线程池线程池的源码会在源码篇章中写这部分是比较重要的内容要掌握。