成都汇智动力

Java开发之高并发必备篇(七)——线程池

作者:汇智动力学院 来源:汇智动力学院
发布日期:2022年10月28日

线程池的使用 我们之前使用线程的时候都是自己手动的通过new...

线程池的使用 我们之前使用线程的时候都是自己手动的通过new Thread等方式创建的,使用完了销毁线程,在开发中这样的操作会造成一些弊端: ◆ 对线程频繁的创建和销毁会消耗系统资源 ◆ 当有空闲线程的时候无法复用它,需要创建新的线程这样响应速慢,效率低下 ◆ 并发线程缺乏统一管理,可能无限制新建线程,相互之间竞争,及可能占用过多系统资源导致死机或OOM(OutOfMemoryError内存溢出) ◆ 缺乏更多功能支持,如延时执行、定期执行等 怎么解决上面的一些问题呢?没错就是使用池化技术了。 线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。线程池可以让我们重用已经存在的线程,降低线程创建和销毁的消耗,提高系统的响应速度,并且线程池可以对线程进行管控,不同类型的线程池还会提供不同的功能,例如:有的可以提供延时或者定时执行任务。 corePoolSize: 核心池的大小,这个参数跟下面讲述的线程池的实现原理有很大的关系。默认情况下,在创建了线程池后,线程池中的线程数为0(除非调用了prestartAllCoreThreads()或者prestartCoreThread()方法,表示在没有任务的时候预先创建好corePoolSize个线程或者一个线程),当有任务来之后,就会创建一个线程去执行任务,当线程池中的线程数目达到corePoolSize后,就会把到达的任务放到缓存队列workQueue当中; workQueue: 一个阻塞任务队列,用来存储等待执行的任务,这个参数的选择也很重要,会对线程池的运行过程产生重大影响,它有三个队列选择: ◆ ArrayBlockintQueue:有数量限制的队列 ◆ LinkedBlockingQueue:没有数量限制的队列 ◆ SynchronousQueue:队列不用于存储数据,数量为0,用于数据的移交,队列中插入和删除操作都是同步执行的。 maximumPoolSize: 线程池*大线程数,这个参数也是一个非常重要的参数,它表示在线程池中*多能创建多少个线程; keepAliveTime: 表示线程没有任务执行时*多保持多久时间会终止。 handler: 表示当拒绝处理任务时的策略,有以下四种取值: ◆ ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。 ◆ ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。 ◆ ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列*前面的任务,然后重新尝试执行任务(重复此过程)。 ◆ ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务。
在JDK中有个Executors类提供了四个静态的方法:newCachedThreadPool、newFixedThreadPool、newScheduledThreadPool、newSingleThreadExecutor可以让我们获取四种不同类型的线程池。这个四个方法都返回一个ExecutorService及其子接口的实现类,这些接口中定义了线程池操作的一些基本操作。下面我们来认识下这四个线程池: 1.newCachedThreadPool 创建一个数量无限制的可缓存的线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。比较适合一些执行任务时间端的线程使用场景。
2.newFixedThreadPool 它比较适合一些执行任务时间长消耗资源大的情况,这样把线程数量控制好不会给系统造成太大的负担。
3.newScheduledThreadPool 创建一个指定大小的线程池,支持延时和周期性任务执行。所以它的应用场景不言而喻了,例如:定时备份、定时检测等;
4.newSingleThreadExecutor
◆ submit(): 表示提交执行一个线程任务,支持Runnable和Callable两种方式,并返回一个代表任务待处理结果的Future对象。 ◆ execute(): 提交执行一个Runnable任务,获取不到任务执行的结果。 ◆ shutdown(): 启动有序关闭,其中先前提交的任务将被执行,但不会接受任何新任务。如果已经关闭,调用没有额外的作用。 ◆ shutdownNow(): 尝试停止所有主动执行的任务,停止等待任务的处理,并返回正在等待执行的任务列表。此方法不等待主动执行的任务终止。 ◆ isShutdown(): 判断线程池是否已经停止。 1.newCachedThreadPool
运行结果:
2.newFixedThreadPool
运行结果:
3.newSingleThreadExecutor
运行结果:
4.newScheduledThreadPool
运行结果:
当我们调用shutdown和shutdownNow的时候查看下任务执行情况: executorService.shutdown()
我们发现shutdown是等待任务执行完之后才结束线程池。 executorService.shutdownNow();

我们发现延迟任务都没有执行到就结束了线程池,所以shutdownNow是不管任务是否执行完都会结束线程池。 总结: 在真实开发中我们需要按照我们的业务需要选择合适的线程池,如果要执行时间短但是任务比较多那么就选择newCachedThreadPool数量不限制的可缓存线程池,如果我们执行任务时间长消耗资源那么我们需要选择newFixedThreadPool这种固定长度的线程池合理控制资源消耗,如果我们执行的任务需要按照顺序执行那么我们需要使用newSingleThreadExecutor,如果我们有延时执行的任务或者周期性执行的任务那么我们需要选择newScheduledThreadPool。 二、算法的设计原则   ①、正确性:首先,算法应当满足以特定的“规则说明”方式给出的需求。其次,对算法是否“正确”的理解可以有以下四个层次:   一、程序语法错误。   二、程序对于几组输入数据能够得出满足需要的结果。   三、程序对于精心选择的、典型、苛刻切带有刁难性的几组输入数据能够得出满足要求的结果。   四、程序对于一切合法的输入数据都能得到满足要求的结果。   PS:通常以第 三 层意义的正确性作为衡量一个算法是否合格的标准。   ②、可读性:算法为了人的阅读与交流,其次才是计算机执行。因此算法应该易于人的理解;另一方面,晦涩难懂的程序易于隐藏较多的错误而难以调试。   ③、健壮性:当输入的数据非法时,算法应当恰当的做出反应或进行相应处理,而不是产生莫名其妙的输出结果。并且,处理出错的方法不应是中断程序执行,而是应当返回一个表示错误或错误性质的值,以便在更高的抽象层次上进行处理。   ④、高效率与低存储量需求:通常算法效率值得是算法执行时间;存储量是指算法执行过程中所需要的*大存储空间,两者都与问题的规模有关。   前面三点 正确性,可读性和健壮性相信都好理解。对于第四点算法的执行效率和存储量,我们知道比较算法的时候,可能会说“A算法比B算法快两倍”之类的话,但实际上这种说法没有任何意义。因为当数据项个数发生变化时,A算法和B算法的效率比例也会发生变化,比如数据项增加了50%,可能A算法比B算法快三倍,但是如果数据项减少了50%,可能A算法和B算法速度一样。所以描述算法的速度必须要和数据项的个数联系起来。也就是“大O”表示法,它是一种算法复杂度的相对表示方式,这里我简单介绍一下,后面会根据具体的算法来描述。   相对(relative):你只能比较相同的事物。你不能把一个做算数乘法的算法和排序整数列表的算法进行比较。但是,比较2个算法所做的算术操作(一个做乘法,一个做加法)将会告诉你一些有意义的东西;   表示(representation):大O(用它*简单的形式)把算法间的比较简化为了一个单一变量。这个变量的选择基于观察或假设。例如,排序算法之间的对比通常是基于比较操作(比较2个结点来决定这2个结点的相对顺序)。这里面就假设了比较操作的计算开销很大。但是,如果比较操作的计算开销不大,而交换操作的计算开销很大,又会怎么样呢?这就改变了先前的比较方式;   然后我们再说说算法的存储量,包括:    程序本身所占空间;    输入数据所占空间;    辅助变量所占空间;   一个算法的效率越高越好,而存储量是越低越好。 三、算法的分类 算法可以宏泛的分为三类: 一,有限的,确定性算法 这类算法在有限的一段时间内终止。他们可能要花很长时间来执行指定的任务,但仍将在一定的时间内终止。这类算法得出的结果常取决于输入值。 二,有限的,非确定算法 这类算法在有限的时间内终止。然而,对于一个(或一些)给定的数值,算法的结果并不是的或确定的。 三,无限的算法 是那些由于没有定义终止定义条件,或定义的条件无法由输入的数据满足而不终止运行的算法。通常,无限算法的产生是由于未能确定的定义终止条件。 Java中常见的算法有: ①、排序 排序就是对一组数据按照一定的顺序(从大到小或者从小到大)进行排序; 常见排序如下: 简单排序:冒泡排序、选择排序、插入排序; 高级排序:快速排序、希尔排序、归并排序、基数排序、鸡尾酒排序等等; ②、递归 递归是一种直接或者间接调用自身的一种算法,递归的目的是简化程序设计使程序更加易读; ③、查找 在一些(有序的/无序的)数据元素中,通过一定的方法找出与给定关键字相同的数据元素就叫做查找; ④、统计 指对有关数据的搜集、整理、计算、分析、解释、表述等的活动。 往期文章 墙裂推荐 [ 1 ] Java开发之高并发必备篇(六)——Lock和ReentrantLock(3) [2 ] Java开发之高并发必备篇(六)——Lock和ReentrantLock(2) [3 ] Java开发之高并发必备篇(六)——Lock和ReentrantLock 原创视频 墙裂推荐 最新就业喜报 ↓↓↓

活动福利 // 1 毕业礼包 | 毕业学员免费赠送《软件测试技术大咖专题课》,助力学员早日突破高薪瓶颈 // 2 入职礼包 |就业学员免费赠送《Java语言开发视频课》及源代码,市场价值12800元 // 3 推荐有奖 |推荐好友成功报名,立得丰厚“伯乐”红包 (欢迎详询校区老师)

详询软件测试&开发培训事宜

加微信咨询
杨老师 @成都汇智动力
微信号:186******73

专业解答各类课程问题、介绍师资和学校情况

微信咨询
相关资讯
汇智2024年12月至2025年1月就业数据新鲜出炉,*高薪资13700元! 全国各校区2025年最新开班时间——2月 日薪1.5K!汇智动力最新就业喜报 全国各校区最新开班时间——2024年3月 全国各校区最新开班时间——2024年4月
相关课程