`

线程池之线程池说明

阅读更多


 一,线程池

 我们知道线程不可能无限制的创建,但是现实需求中遇到并发请求多任务的时候,会用多线程来处理,但是这么多的线程又不可能全部创建出来,这时我们就会想到线程池了,

说道线程池,它其实就是一种管理多线程一种手段。下面的代码是描述要测试的使用的代码,

 

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 直接报错 抛异常

 

 

 

  • 大小: 109.7 KB
分享到:
评论

相关推荐

    Java线程池使用说明

    Java线程池是Java并发编程中的重要组件,它能够有效地管理和复用线程,从而提高程序的执行效率和降低资源消耗。在JDK 1.5版本之前,Java对线程池的支持非常有限,而在JDK 1.5之后,加入了java.util.concurrent包,...

    java线程池完整代码

    描述 "Java 线程池完整源码" 说明了这篇文章的内容是关于 Java 线程池的完整实现代码,包括线程池的源代码、配置文件的解析和线程池的管理等方面。 标签解析 标签 "Java 线程池完整源码" 说明了这篇文章的主题是...

    java线程池使用后到底要关闭吗

    说明线程未被回收。 因此,使用完线程池后一定要关闭,否则可能会导致内存泄露和应用崩溃。关闭线程池可以使用shutdown()或shutdownNow()方法。shutdown()方法将等待所有任务执行完毕后销毁线程,而shutdownNow()...

    java线程池概念.txt

    corePoolSize:核心池的大小,在创建了线程池后,线程池中的线程数为0,当有任务来之后,就会创建一个线程去执行任务,当线程池中的线程数目达到corePoolSize后,就会把到达的任务放到缓存队列当中; ...

    简单的线程池模型 (Dephi版),线程池

    线程池是一种在计算机编程中优化并发处理的机制,它允许多个任务或工作单元在一组预先创建的线程上并行执行。在Delphi编程环境中,线程池的实现通常涉及对操作系统提供的API或者VCL(Visual Component Library)组件...

    简单的线程池的.net实现

    "readme.txt"文件通常会提供项目简介、使用说明、注意事项等信息,对于理解整个项目非常有帮助。 "DotNetInfra.ThreadingServices.sln"是Visual Studio的解决方案文件,包含了项目的所有配置信息,可以用来打开和...

    Python 使用threading+Queue实现线程池示例

    记创建线程消耗时间T1,执行任务消耗时间T2,销毁线程消耗时间T3,如果T1+T3&gt;T2,那说明开启一个线程来执行这个任务太不划算了!在线程池缓存线程可用已有的闲置线程来执行新任务,避免了创建/销毁带来的系统开销。 ...

    线程池的VC实现例子

    而"threadpool.rar"可能是另一个线程池的实现版本,"VC实现线程池.txt"很可能是对VC环境下线程池实现的文本说明。 通过学习和分析这些文件,我们可以更深入地理解线程池的原理,以及如何在VC环境中有效地利用线程池...

    Windows下一个比较完美的线程池实现和示例

    Windows下一个比较完美的线程池实现和示例 本线程池提供了如下功能: 1.能根据任务个数和当前线程的多少在最小/最大线程个数之间自动调整(Vista后的系统有 SetThreadpoolThreadMaximum 等函数有...详细说明参见本人博客

    易语言线程池类模块源码

    `源码使用说明.txt`文件则提供了关于如何使用这个模块的指导,包括如何导入到项目中,以及如何正确调用其提供的API进行任务处理。 学习易语言线程池类模块源码,不仅可以帮助开发者理解和实践多线程编程,还能提升...

    visual c++实现线程池的例子threadpooldemosrc.rar

    虽然示例代码没有明确说明是否使用了Boost库,但它是C++开发者常用来支持多线程和并发操作的库,因此在理解线程池的实现时,了解Boost库的相关知识是很有帮助的。 "thread_pool.rar"可能是另一个线程池的实现,或者...

    完成端口高效线程池

    4. 文档:关于如何安装、配置和使用PAThreadPool的说明文档,可能包括API参考和使用示例。 5. 构建脚本:用于编译和打包库的自动化脚本,如Makefile或MSBuild项目文件。 使用PAThreadPool的开发者可以从以下几个...

    c++线程池类代码实现

    成员变量说明 - **m_ThreadPool** 和 **m_TrashThread**:分别表示当前线程池和待销毁线程的集合。 - **m_Tasks**:任务队列,用于存储等待处理的任务。 - **m_csTasksLock** 和 **m_csThreadPoolLock**:用于保护...

    C++线程池源码

    `www.pudn.com.txt`可能是下载这些源码的来源信息,或者是一份说明文档,但具体内容需要打开文件查看。 在C++中实现线程池,可能会使用到`&lt;thread&gt;`库,其中包括了`std::thread`类,用于创建和管理线程。此外,`...

    易语言完美的线程池源码

    - `read.txt`:可能包含有关线程池的文档或说明。 - `CommonSupport.sln`:这是C++的Visual Studio解决方案文件,包含了一个或多个项目的配置。 - `lib`、`soure`、`static_lib`:这些可能是库文件、源代码文件夹...

    基于java编写的智能电表采集系统源码+配置说明+流程说明(使用线程池进行采集,采集频率为5S).zip

    基于java编写的智能电表采集系统源码+配置说明+流程说明(使用线程池进行采集,采集频率为5S,实现电表协议解析存入数据库).zip 使用java编写的智能电表采集系统,使用线程池进行采集,采集频率为5S,实现电表协议...

    Java concurrency线程池之线程池原理(四)_动力节点Java学院整理

    结果说明:结果说明:线程池pool的"最大池大小"和"核心池大小"都为1(THREADS_SIZE),"线程池"的阻塞队列容量为1(CAPACITY)。当我们新建10个任务,并将它们添加到线程池中时,只有第一个任务被执行,其余的任务被丢弃...

    java线程池使用说明[借鉴].pdf

    Java线程池是Java语言中一个非常重要的特性,特别是在多线程编程中,它通过管理和控制线程的创建和执行,有效地提高了程序的性能和资源利用率。线程池的引入始于JDK 1.5,它引入了`java.util.concurrent`包,提供了`...

    vc开发的线程池类,内有详细说明

    这个名为“线程池类”的压缩包文件,可能包含了一个自定义的线程池类实现,以及相关的使用说明。 线程池的基本工作原理是维护一组可重用的线程,这些线程预先创建并在空闲时等待新任务的到来。当有新的任务需要执行...

Global site tag (gtag.js) - Google Analytics