java线程池中线程数量到底是几

首先让我们来了解一下Java线程池。

线程池是一种线程使用方式的抽象,它可以优化多线程的资源使用情况。通过重复利用已创建的线程,降低线程创建和销毁的开销,提高响应速度。

而Java中的线程池主要由ThreadPoolExecutor类实现,该类有以下构造方法

public ThreadPoolExecutor(int corePoolSize, //核心线程池大小
                              int maximumPoolSize, //最大线程池大小
                              long keepAliveTime, //线程生存时间
                              TimeUnit unit, //时间单位
                              BlockingQueue<Runnable> workQueue, //任务队列
                              ThreadFactory threadFactory, //线程工厂
                              RejectedExecutionHandler handler) //异常处理器

接下来我们来解答问题:Java线程池中线程数量到底是几

线程池中的线程数量实际上是动态变化的,它由核心线程池大小(corePoolSize)、最大线程池大小(maximumPoolSize)、任务队列(workQueue)等参数共同决定。

具体来说,线程池中线程数量受以下几个条件制约:

  1. 当线程池中运行的线程数小于corePoolSize时,新加入的任务会创建一个新的线程来执行任务,并将该线程放入线程池中,因此线程池中运行的线程数就会增加。

  2. 当线程池中运行的线程数达到corePoolSize时,新加入的任务会被加入到任务队列(workQueue)中等待执行,在任务队列中等待的任务不会立即执行。

  3. 如果任务队列已满,且当前线程池中的线程数小于maximumPoolSize,则线程池会创建一个新的线程来执行任务,因此线程池中运行的线程数就会增加。

  4. 如果当前线程池中运行的线程数已经达到了maximumPoolSize,且任务队列中已经有任务在等待执行,此时线程池会使用RejectedExecutionHandler处理器对任务进行处理,如使用AbortPolicy则会抛出RejectedExecutionException异常,表示任务无法处理。

示例1:

ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 20, 60L, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(10), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
for(int i=0;i<50;i++){
    executor.execute(new Runnable(){
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName()+" is running!");
        }
    });
    System.out.println("Current pool size: "+executor.getPoolSize()+" ,Queue size: "+executor.getQueue().size());
}
executor.shutdown();

在这个示例中,我们创建了一个核心线程池大小为10,最大线程池大小为20的线程池。

我们向线程池中提交了50个任务,每个任务只是输出当前线程的名称。

控制台输出如下:

Current pool size: 1 ,Queue size: 0
Current pool size: 2 ,Queue size: 0
Current pool size: 3 ,Queue size: 0
Current pool size: 4 ,Queue size: 0
Current pool size: 5 ,Queue size: 0
Current pool size: 6 ,Queue size: 0
Current pool size: 7 ,Queue size: 0
Current pool size: 8 ,Queue size: 0
Current pool size: 9 ,Queue size: 0
Current pool size: 10 ,Queue size: 0
Current pool size: 10 ,Queue size: 1
Current pool size: 10 ,Queue size: 2
Current pool size: 10 ,Queue size: 3
Current pool size: 10 ,Queue size: 4
Current pool size: 10 ,Queue size: 5
Current pool size: 10 ,Queue size: 6
Current pool size: 10 ,Queue size: 7
Current pool size: 10 ,Queue size: 8
Current pool size: 10 ,Queue size: 9
Current pool size: 10 ,Queue size: 10
Exception in thread "main" java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.FutureTask@603c5a11 rejected from java.util.concurrent.ThreadPoolExecutor@27c170f0[Running, pool size = 10, active threads = 10, queued tasks = 10, completed tasks = 0]

我们可以看到,在任务提交的前10个任务,线程池中都会创建一个新的线程来执行任务,线程池中最大线程数量不会超过10。

当任务队列已经满时,线程池中运行的线程数量已经达到了10个(corePoolSize大小),此时新加入的任务将会被拒绝执行。

示例2:

ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 20, 60L, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(10), Executors.defaultThreadFactory(), new ThreadPoolExecutor.CallerRunsPolicy());
for(int i=0;i<30;i++){
    executor.execute(new Runnable(){
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName()+" is running!");
            try {
                Thread.sleep(1000L);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    });
    System.out.println("Current pool size: "+executor.getPoolSize()+" ,Queue size: "+executor.getQueue().size());
}
executor.shutdown();

在这个示例中,我们提交了30个任务,每个任务会输出当前线程名称并休眠1秒钟。

通过设置线程池的CallerRunsPolicy处理器,当线程池被拒绝执行时,该处理器会让当前线程执行任务。

控制台输出如下:

Current pool size: 1 ,Queue size: 0
Current pool size: 2 ,Queue size: 0
Current pool size: 3 ,Queue size: 0
Current pool size: 4 ,Queue size: 0
Current pool size: 5 ,Queue size: 0
Current pool size: 6 ,Queue size: 0
Current pool size: 7 ,Queue size: 0
Current pool size: 8 ,Queue size: 0
Current pool size: 9 ,Queue size: 0
Current pool size: 10 ,Queue size: 0
Current pool size: 10 ,Queue size: 1
Current pool size: 10 ,Queue size: 2
Current pool size: 10 ,Queue size: 3
Current pool size: 10 ,Queue size: 4
Current pool size: 10 ,Queue size: 5
pool-1-thread-12 is running!
Current pool size: 10 ,Queue size: 6
pool-1-thread-13 is running!
Current pool size: 10 ,Queue size: 7
pool-1-thread-14 is running!
Current pool size: 10 ,Queue size: 8
pool-1-thread-15 is running!
Current pool size: 10 ,Queue size: 9
pool-1-thread-16 is running!
Current pool size: 10 ,Queue size: 10
pool-1-thread-17 is running!
pool-1-thread-1 is running!
pool-1-thread-2 is running!
pool-1-thread-3 is running!
pool-1-thread-4 is running!
pool-1-thread-5 is running!
pool-1-thread-6 is running!
pool-1-thread-7 is running!
pool-1-thread-8 is running!
pool-1-thread-9 is running!
pool-1-thread-10 is running!
pool-1-thread-11 is running!

我们可以看到,在任务提交的前10个任务,线程池中都会创建一个新的线程来执行任务,线程池中最大线程数量不会超过10。

当任务队列已经满时,线程池中运行的线程数量已经达到了10个(corePoolSize大小),后续任务被拒绝执行,但是使用了CallerRunsPolicy处理器,当前线程(main线程)执行了被拒绝的任务。

综上所述,Java线程池中线程数量实际上是动态变化的,受多个因素的制约。我们应该根据实际情况进行合理的配置。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:java线程池中线程数量到底是几 - Python技术站

(0)
上一篇 2023年5月26日
下一篇 2023年5月26日

相关文章

  • PHP Parse Error: syntax error, unexpected $end 错误的解决办法

    当PHP代码运行过程中发生了语法错误,导致编译器无法正确解析代码时,会出现“PHP Parse Error: syntax error, unexpected $end”错误。这一错误的出现会导致程序运行异常终止。本文将详细讲解此类错误的解决办法,帮助读者更好地理解和解决这种常见的错误。 原因分析 这种错误通常是由于编写代码时,存在以下几种问题导致的:1. …

    Java 2023年6月15日
    00
  • notepad++支持什么语言? notepad语言格式设置技巧

    关于”Notepad++支持什么语言”和”Notepad语言格式设置技巧”,以下是详细攻略: Notepad++支持哪些编程语言? Notepad++是一款常用的文本编辑器,它支持多种编程语言和标记语言。下面是Notepad++支持的一些主要编程语言: C、C++、C#、Java、Python、Ruby等大部分主流编程语言。 HTML、CSS、JavaScr…

    Java 2023年6月15日
    00
  • JSP分页显示的实例代码

    JSP分页显示的实例代码需要以下步骤: 1. 准备数据 首先,我们需要准备一些数据,以便在JSP页面中分页显示。可以从数据库中查询相关数据,或者手动设置一些数据。 int pageSize = 5; //每页显示5条数据 int currentPage = 1; //当前页码 List<String> dataList = new ArrayLi…

    Java 2023年6月15日
    00
  • 关于Java中的dozer对象转换问题

    关于Java中的Dozer对象转换问题,推荐以下完整攻略进行讲解: 什么是Dozer对象转换器? Dozer是一个JavaBean映射的转换工具,它可以将一个Java对象转换为另一个Java对象。Dozer提供简单的反射功能,自动识别不同类之间的相同名称的字段,并自动映射它们。Dozer支持类之间的复制、聚合关系、继承、XML配置映射等特性。 使用Dozer…

    Java 2023年5月26日
    00
  • JAVA 对象创建与对象克隆

    JAVA 对象创建与对象克隆 在 Java 中,对象创建与对象克隆是非常重要的知识点。 对象创建 Java 中的对象常见的有以下几种创建方式: 使用 new 关键字 使用 new 关键字创建对象是最常见的一种方式,通过这种方式创建出来的对象是一个新的对象实例,具有独立的地址空间。例子如下: public class Person { private Stri…

    Java 2023年5月26日
    00
  • SpringBoot请求处理之常用参数注解介绍与源码分析

    SpringBoot请求处理之常用参数注解介绍与源码分析 在Spring Boot应用程序中,我们需要处理各种类型的请求。在处理请求时,我们需要使用不同的参数注解来获取请求参数。本文将详细介绍Spring Boot请求处理中常用的参数注解,并分析其源代码。 @RequestParam @RequestParam注解用于获取请求参数。以下是一个示例: @Get…

    Java 2023年5月15日
    00
  • SpringBoot整合Mybatis注解开发的实现代码

    接下来我将以以下步骤为例,详细讲解SpringBoot整合Mybatis注解开发的实现代码: 配置Mybatis 首先,在Spring Boot配置文件中添加Mybatis的相关配置,如下所示: mybatis: mapper-locations: classpath:mapper/*.xml configuration: map-underscore-to…

    Java 2023年5月20日
    00
  • Java struts2请求源码分析案例详解

    Java struts2请求源码分析攻略 概述 在Java web开发中,struts2框架是一个常用的web应用框架。为了深入了解struts2框架的使用和工作原理,我们需要对其请求源码进行分析。 步骤 步骤1:打开struts2源码 首先,我们需要下载struts2框架的源代码,并导入到开发工具中。源代码可以在struts2官网或者GitHub上下载。 …

    Java 2023年5月20日
    00
合作推广
合作推广
分享本页
返回顶部