一,线程池
我们知道线程不可能无限制的创建,但是现实需求中遇到并发请求多任务的时候,会用多线程来处理,但是这么多的线程又不可能全部创建出来,这时我们就会想到线程池了,
说道线程池,它其实就是一种管理多线程一种手段。下面的代码是描述要测试的使用的代码,
package com.test.thread; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import org.junit.Test; public class TestThreadPool { /** * 一个阻塞队列 */ BlockingQueue<Runnable> queues=new LinkedBlockingQueue<Runnable>(10); /** * 线程池 初始化10个线程 最大线程数量为20个,空闲时间为0L秒 */ ThreadPoolExecutor pool= new ThreadPoolExecutor(10, 20,0L,TimeUnit.MICROSECONDS,queues); /** * * @param threadNum 执行线程数量 * @throws InterruptedException */ private void testThreadPool(int threadNum)throws InterruptedException{ for(int i=1;i<=threadNum;i++){ pool.execute(new Task("aa@"+i)); } //停顿一秒钟等待线程池中初始化线程都启动 Thread.sleep(1000); //打印当前阻塞队列中有多少线程 System.out.println("此时阻塞队列有多个少任务:"+"数量->"+queues.size()+",具体线程->"+queues); System.out.println("线程池中执行的线程:"+pool.getActiveCount()); /** * shutdown方法的时候,线程池不再接收任何新任务,但此时线程池并不会立刻退出,直到添加到线程池中的任务都已经处理完成,才会退出。 * 在调用shutdown方法后我们可以在一个死循环里面用isTerminated方法判断是否线程池中的所有线程已经执行完毕,如果子线程都结束了,我们就可以做关闭流等后续操作了。 */ pool.shutdown(); while(true){ if(pool.isTerminated()){ System.out.println("所有任务执行完成....."); break; } Thread.sleep(200); } } /** * 测试5个线程 * @throws InterruptedException */ @Test public void testThreadPool5() throws InterruptedException { testThreadPool(5); } /** * 测试15个线程 * @throws InterruptedException */ @Test public void testThreadPool15() throws InterruptedException{ testThreadPool(15); } /** * 测试25个线程 * @throws InterruptedException */ @Test public void testThreadPool25() throws InterruptedException{ testThreadPool(25); } /** * 测试45个线程 * @throws InterruptedException */ @Test public void testThreadPool45() throws InterruptedException{ testThreadPool(45); } } class Task implements Runnable{ String name; public Task(String name) { this.name=name; } @Override public void run() { System.out.println("线程["+name+"]启动... 开始执行任务"); try { Thread.sleep(30000L); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("线程["+name+"]结束--- 完成任务"); } @Override public String toString() { return name; } }
(1)当 执行testThreadPool5()方法时候 ,这里 线程为5个数量
其中打印结果
线程[aa@2]启动... 开始执行任务 线程[aa@1]启动... 开始执行任务 线程[aa@4]启动... 开始执行任务 线程[aa@3]启动... 开始执行任务 线程[aa@5]启动... 开始执行任务 此时阻塞队列有多个少任务:数量->0,具体线程->[] 线程池中执行的线程:5 线程[aa@1]结束--- 完成任务 线程[aa@5]结束--- 完成任务 线程[aa@3]结束--- 完成任务 线程[aa@4]结束--- 完成任务 线程[aa@2]结束--- 完成任务 所有任务执行完成.....
从打印结果中我们可以看到 由于 给定的执行线程数量5 小于初始化数量10 所以 不会多余的线程放入阻塞队列中
(2)当执行testThreadPool15() 方法,这里给定执行的线程为15
其中打印结果
线程[aa@1]启动... 开始执行任务 线程[aa@3]启动... 开始执行任务 线程[aa@2]启动... 开始执行任务 线程[aa@4]启动... 开始执行任务 线程[aa@5]启动... 开始执行任务 线程[aa@6]启动... 开始执行任务 线程[aa@7]启动... 开始执行任务 线程[aa@9]启动... 开始执行任务 线程[aa@8]启动... 开始执行任务 线程[aa@10]启动... 开始执行任务 此时阻塞队列有多个少任务:数量->5,具体线程->[aa@11, aa@12, aa@13, aa@14, aa@15] 线程池中执行的线程:10 线程[aa@2]结束--- 完成任务 线程[aa@1]结束--- 完成任务 线程[aa@3]结束--- 完成任务 线程[aa@11]启动... 开始执行任务 线程[aa@6]结束--- 完成任务 线程[aa@5]结束--- 完成任务 线程[aa@15]启动... 开始执行任务 线程[aa@4]结束--- 完成任务 线程[aa@12]启动... 开始执行任务 线程[aa@13]启动... 开始执行任务 线程[aa@14]启动... 开始执行任务 线程[aa@10]结束--- 完成任务 线程[aa@7]结束--- 完成任务 线程[aa@9]结束--- 完成任务 线程[aa@8]结束--- 完成任务 线程[aa@11]结束--- 完成任务 线程[aa@15]结束--- 完成任务 线程[aa@12]结束--- 完成任务 线程[aa@13]结束--- 完成任务 线程[aa@14]结束--- 完成任务 所有任务执行完成.....
从打印结果中我们可以看到 由于 给定的执行线程数量15 大于初始化数量10 小于最大线程数量20,所以 多余的线程放入阻塞队列中为5个 随着前十个线程逐渐执行完成时, 阻塞队列中的线程也开始加入执行中,最终队列全部完成
(3)当执行testThreadPool25() 方法,这里给定执行的线程为25
其中打印结果
线程[aa@1]启动... 开始执行任务 线程[aa@4]启动... 开始执行任务 线程[aa@3]启动... 开始执行任务 线程[aa@5]启动... 开始执行任务 线程[aa@6]启动... 开始执行任务 线程[aa@2]启动... 开始执行任务 线程[aa@7]启动... 开始执行任务 线程[aa@8]启动... 开始执行任务 线程[aa@9]启动... 开始执行任务 线程[aa@10]启动... 开始执行任务 线程[aa@21]启动... 开始执行任务 线程[aa@23]启动... 开始执行任务 线程[aa@22]启动... 开始执行任务 线程[aa@24]启动... 开始执行任务 线程[aa@25]启动... 开始执行任务 此时阻塞队列有多个少任务:数量->10,具体线程->[aa@11, aa@12, aa@13, aa@14, aa@15, aa@16, aa@17, aa@18, aa@19, aa@20] 线程池中执行的线程:15 线程[aa@10]结束--- 完成任务 线程[aa@2]结束--- 完成任务 线程[aa@7]结束--- 完成任务 线程[aa@5]结束--- 完成任务 线程[aa@8]结束--- 完成任务 线程[aa@4]结束--- 完成任务 线程[aa@9]结束--- 完成任务 线程[aa@16]启动... 开始执行任务 线程[aa@1]结束--- 完成任务 线程[aa@14]启动... 开始执行任务 线程[aa@15]启动... 开始执行任务 线程[aa@13]启动... 开始执行任务 线程[aa@3]结束--- 完成任务 线程[aa@19]启动... 开始执行任务 线程[aa@12]启动... 开始执行任务 线程[aa@11]启动... 开始执行任务 线程[aa@6]结束--- 完成任务 线程[aa@20]启动... 开始执行任务 线程[aa@18]启动... 开始执行任务 线程[aa@17]启动... 开始执行任务 线程[aa@23]结束--- 完成任务 线程[aa@21]结束--- 完成任务 线程[aa@22]结束--- 完成任务 线程[aa@24]结束--- 完成任务 线程[aa@25]结束--- 完成任务 线程[aa@16]结束--- 完成任务 线程[aa@17]结束--- 完成任务 线程[aa@18]结束--- 完成任务 线程[aa@20]结束--- 完成任务 线程[aa@11]结束--- 完成任务 线程[aa@12]结束--- 完成任务 线程[aa@19]结束--- 完成任务 线程[aa@13]结束--- 完成任务 线程[aa@15]结束--- 完成任务 线程[aa@14]结束--- 完成任务 所有任务执行完成.....
从打印结果中我们可以看到 由于 给定的执行线程数量25 大于初始化数量10 大于最大线程数量20,所以 多余的线程放入阻塞队列中为10个 这是线程池中就有15个线程在执行 (这个数量小于最大数量限制20)
(3)当执行testThreadPool45() 方法,这里给定执行的线程为45
这时打印结果会报错 如下图
由于 给定的执行线程数量25 大于初始化数量10 大于最大线程数量20,而阻塞队列最多可以放置10个 这是线程池中就有25个线程执行 但是由于线程池最大数量是20 不能同时执行25个所以报错
综上所述 假设 执行线程数量 threadNum,初始化线程数量 corePoolSize, 线程最大允许执行数量maximumPoolSize ,阻塞队列容量queueNums
1,当threadNum<corePoolSize 时候直接执行,阻塞队列没有多余线程可放
2,当corePoolSize<threadNum<maximumPoolSize ,阻塞队列线程数量min(queueNums,threadNum-corePoolSize) 执行的线程数量为corePoolSize
3,当threadNum>maximumPoolSize且 (threadNum-min(queueNums,threadNum-corePoolSize))<maximumPoolSize 阻塞队列线程数量min(queueNums,threadNum-corePoolSize) 执行的线程数量为threadNum-min(queueNums,threadNum-corePoolSize)
4,当 3,当threadNum>maximumPoolSize且 (threadNum-min(queueNums,threadNum-corePoolSize))>maximumPoolSize 直接报错 抛异常
相关推荐
Java线程池是Java并发编程中的重要组件,它能够有效地管理和复用线程,从而提高程序的执行效率和降低资源消耗。在JDK 1.5版本之前,Java对线程池的支持非常有限,而在JDK 1.5之后,加入了java.util.concurrent包,...
描述 "Java 线程池完整源码" 说明了这篇文章的内容是关于 Java 线程池的完整实现代码,包括线程池的源代码、配置文件的解析和线程池的管理等方面。 标签解析 标签 "Java 线程池完整源码" 说明了这篇文章的主题是...
说明线程未被回收。 因此,使用完线程池后一定要关闭,否则可能会导致内存泄露和应用崩溃。关闭线程池可以使用shutdown()或shutdownNow()方法。shutdown()方法将等待所有任务执行完毕后销毁线程,而shutdownNow()...
corePoolSize:核心池的大小,在创建了线程池后,线程池中的线程数为0,当有任务来之后,就会创建一个线程去执行任务,当线程池中的线程数目达到corePoolSize后,就会把到达的任务放到缓存队列当中; ...
线程池是一种在计算机编程中优化并发处理的机制,它允许多个任务或工作单元在一组预先创建的线程上并行执行。在Delphi编程环境中,线程池的实现通常涉及对操作系统提供的API或者VCL(Visual Component Library)组件...
"readme.txt"文件通常会提供项目简介、使用说明、注意事项等信息,对于理解整个项目非常有帮助。 "DotNetInfra.ThreadingServices.sln"是Visual Studio的解决方案文件,包含了项目的所有配置信息,可以用来打开和...
记创建线程消耗时间T1,执行任务消耗时间T2,销毁线程消耗时间T3,如果T1+T3>T2,那说明开启一个线程来执行这个任务太不划算了!在线程池缓存线程可用已有的闲置线程来执行新任务,避免了创建/销毁带来的系统开销。 ...
而"threadpool.rar"可能是另一个线程池的实现版本,"VC实现线程池.txt"很可能是对VC环境下线程池实现的文本说明。 通过学习和分析这些文件,我们可以更深入地理解线程池的原理,以及如何在VC环境中有效地利用线程池...
Windows下一个比较完美的线程池实现和示例 本线程池提供了如下功能: 1.能根据任务个数和当前线程的多少在最小/最大线程个数之间自动调整(Vista后的系统有 SetThreadpoolThreadMaximum 等函数有...详细说明参见本人博客
`源码使用说明.txt`文件则提供了关于如何使用这个模块的指导,包括如何导入到项目中,以及如何正确调用其提供的API进行任务处理。 学习易语言线程池类模块源码,不仅可以帮助开发者理解和实践多线程编程,还能提升...
虽然示例代码没有明确说明是否使用了Boost库,但它是C++开发者常用来支持多线程和并发操作的库,因此在理解线程池的实现时,了解Boost库的相关知识是很有帮助的。 "thread_pool.rar"可能是另一个线程池的实现,或者...
- `read.txt`:可能包含有关线程池的文档或说明。 - `CommonSupport.sln`:这是C++的Visual Studio解决方案文件,包含了一个或多个项目的配置。 - `lib`、`soure`、`static_lib`:这些可能是库文件、源代码文件夹...
4. 文档:关于如何安装、配置和使用PAThreadPool的说明文档,可能包括API参考和使用示例。 5. 构建脚本:用于编译和打包库的自动化脚本,如Makefile或MSBuild项目文件。 使用PAThreadPool的开发者可以从以下几个...
成员变量说明 - **m_ThreadPool** 和 **m_TrashThread**:分别表示当前线程池和待销毁线程的集合。 - **m_Tasks**:任务队列,用于存储等待处理的任务。 - **m_csTasksLock** 和 **m_csThreadPoolLock**:用于保护...
`www.pudn.com.txt`可能是下载这些源码的来源信息,或者是一份说明文档,但具体内容需要打开文件查看。 在C++中实现线程池,可能会使用到`<thread>`库,其中包括了`std::thread`类,用于创建和管理线程。此外,`...
基于java编写的智能电表采集系统源码+配置说明+流程说明(使用线程池进行采集,采集频率为5S,实现电表协议解析存入数据库).zip 使用java编写的智能电表采集系统,使用线程池进行采集,采集频率为5S,实现电表协议...
结果说明:结果说明:线程池pool的"最大池大小"和"核心池大小"都为1(THREADS_SIZE),"线程池"的阻塞队列容量为1(CAPACITY)。当我们新建10个任务,并将它们添加到线程池中时,只有第一个任务被执行,其余的任务被丢弃...
Java线程池是Java语言中一个非常重要的特性,特别是在多线程编程中,它通过管理和控制线程的创建和执行,有效地提高了程序的性能和资源利用率。线程池的引入始于JDK 1.5,它引入了`java.util.concurrent`包,提供了`...
这个名为“线程池类”的压缩包文件,可能包含了一个自定义的线程池类实现,以及相关的使用说明。 线程池的基本工作原理是维护一组可重用的线程,这些线程预先创建并在空闲时等待新任务的到来。当有新的任务需要执行...