专栏首页SpringBootjava 线程池简介

java 线程池简介

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

本文链接:https://blog.csdn.net/qq_32534855/article/details/99608297

简介

什么是“池” : 软件中的“池”,可以理解为计划经济时代的工厂。 首先,作为工厂,你要管理好你生产的东西,老王从你工厂这里拿走了一把斧头,改天他不需要了,还回来,你可以把这把斧头借给老赵; 其次,你又不能无限制的生产,毕竟在资源极度匮乏的时代,如果都被你拿去生产了,其他要用到资源的地方怎么办? 总结成两点,“池”的作用: 复用已有资源 控制资源总量 数据库连接池是这样,线程池也是如此。 你一个任务过来了,我发现池子里有没事干并且还活着的线程,来,拿去用,我也不用费事给你创建一条线程了,要知道线程的创建和销毁可都是麻烦事; 你一个任务过来了,我发现池子的线程都在忙,并且现在池子的线程已经太多了,再不限制下去就要内存溢出了,来,排队去~

Java中常见的4种线程池:

1    FixedThreadPool 2    CachedThreadPool 3    ScheduledThreadPool 4    SingleThreadExecutor

FixedThreadPool: 固定线程数的线程池,可控制线程最大并发数,超出的线程会在队列中等待。

这里的线程数是固定的,每个线程都会从任务队列中去取任务,由于这个取的动作是并发的,所以要求任务队列具有线程安全的特性,所以通常会使用阻塞队列来实现。

CachedThreadPool: 可缓存线程池(特点: 无界线程池,具有自动回收多余线程的功能)

在这种情况下,我们的线程数量并不是固定的,而且我们也没有一个用来存储已提交任务的队列;相反,这种线程池用有一个同步队列(synchronous queue),它只能存储1个Task。每当我们提交了一个任务给线程池,这个任务就会被放到这个队列中。此时,线程池会在已经创建的所有线程中去寻找空闲的线程,并把这一个任务交给这个空闲的线程去执行。如果线程池没能找到一个空闲的线程,说明所有的线程都在工作,那么它就会新建一个线程,并把这个任务交给这个刚刚创建好的线程去执行,这样就达到了动态增加线程数量的目的。

ScheduledThreadPool 支持定时及周期性任务执行的线程池。

这种线程池是专门服务于需要延迟或周期执行任务的场景,例如我们需要每10秒进行一次安全检查。  ScheduledThreadPool主要有3种执行任务的方法:  1.    service.schedule 延迟且单次执行,例如10秒后执行,总共只执行一次  2.    service.scheduleAtFixedRate 每间隔固定时间执行一次,例如每10秒执行一次  3.    service.scheduleAtFixedDelay 在上一个任务执行后,间隔固定时间再次执行。例如:每个Task需要执行5分钟,那么我们可以设定在这个Task直接结束后,等待1分钟再执行下一次的任务,所以最终的效果就是每6分钟该任务会被执行一次。  scheduleAtFixedRate和scheduleAtFixedDelay的区别在于,scheduleAtFixedRate是以任务开始执行的时间为起点,开始计时,而scheduleAtFixedDelay是以任务执行完毕为时间起点进行计时。

这里用来存储Task的queue是一个延迟队列,延迟队列的特点是:不是先进先出,而是会按照延迟时间的长短来排序,下一个即将执行的任务会排到队列的最前面。我们来举个例子:例如我们往这个队列中,放一个延迟10分钟执行的任务,然后再放一个延迟10秒钟执行的任务。通常而言,如果不是延迟队列而是普通队列,那么按照先进先出的排列规则,也就是第一个放置的会排在最前面,也就是延迟10分钟执行的那个任务会放在最前面,但是由于我们此时使用的是延迟队列,延迟队列在排放各个任务的位置的时候,会根据延迟时间的长短来排放。所以。我们第二个放置的延迟10秒钟执行的那个任务,反而会排在延迟10分钟的任务的前面,因为它的执行时间更早。

SingleThreadExecutor 单线程的线程池:它只会用唯一的工作线程来执行任务,它的原理和FixedThreadPool是一样的,但是此时的线程数量被设置为了1。这里的这一个线程,会不停地从任务队列里取任务,然后执行。如果线程在执行任务的时候,遇到了异常导致线程执行中断,那么线程池会重新创建一个线程继续执行后续的任务,而不会永远地中断执行任务。

使用场景:目的是保证所有任务按照提交任务的顺序执行。例如我们想要让第二个任务必须在第一个任务之后执行,同理,或者我们希望让任务三在任务二之后执行,这种场景下就需要用到SingleThreadExecutor。因为执行任务的线程只有一个,所以我们可以保证执行的顺序,而之前那几种线程池在执行的时候,由于有多个线程同时执行,所以我们不能保证各个任务之间的执行顺序。

以上4种线程池的构造函数的参数: 其中fixedThreadPool的keepAliveTime是0秒,这里的0代表永久,也就是fixedThreadPool不会kill任何一个idle的线程,即便该线程无事可做(不执行Task)。 newCachedThreadPool的参数指定了corePoolSize为0,所以CachedThreadPool在最开始的时候并不会创建线程,直到有Task进来,需要线程工作的时候才会创建线程。而可以看出CachedThreadPool的maxPoolSize的值是Integer.MAX_VALUE,这可能会创建数量非常多的线程,甚至导致OOM。 ScheduledThreadPool和SingleThreadPool也是同理。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • tomcat加入服务,可以开机自启

    3.开启服务 net start tomcat       关闭服务 net stop tomcat       

    DencyCheng
  • springboot 项目启动读取按照顺序读取配置文件

    版权声明:本文为博主原创文章,未经博主允许不得转载。

    DencyCheng
  • Swagger2 注解说明

    DencyCheng
  • 五种线程池的对比与使用

    通过源码可以看出底层调用的是ThreadPoolExecutor方法,传入一个同步的阻塞队列实现缓存。

    爱撸猫的杰
  • Linux并发(多线程协作)

    一个程序里的线程数,就像一家公司里的员工数一样,太少了忙不过来,太多了入不敷出。因此我们需要有更好的机制来协调它们。

    用户2617681
  • Java多线程之细说线程池

    前言   在认识线程池之前,我们需要使用线程就去创建一个线程,但是我们会发现有一个问题:    如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就...

    用户1195962
  • Java中高级面试题部分答案解析(4)

    这里选了几道高频面试题以及一些解答。不一定全部正确,有一些是没有固定答案的,如果发现有错误的欢迎纠正,如果有更好的回答,热烈欢迎留言探讨。

    java思维导图
  • 40 个Java多线程问题总结

    原文地址:http://www.cnblogs.com/xrq730/p/5060921.htm

    一个优秀的废人
  • 那些有趣的代码(一) —— 有点萌的 Tomcat 的线程池

    最近抓紧时间看看了看tomcat 的源代码。发现了一些有趣的代码,应该会写一系列文章和大家分享一下。

    用户2060079
  • 一文教你安全的关闭线程池

    上篇文章 ShutdownHook- Java 优雅停机解决方案 提到应用停机时需要释放资源,关闭连接。对于一些定时任务或者网络请求服务将会使用线程池,当应用停...

    andyxh

扫码关注云+社区

领取腾讯云代金券