首先让我们来了解一下Java线程池。
线程池是一种线程使用方式的抽象,它可以优化多线程的资源使用情况。通过重复利用已创建的线程,降低线程创建和销毁的开销,提高响应速度。
而Java中的线程池主要由ThreadPoolExecutor类实现,该类有以下构造方法
public ThreadPoolExecutor(int corePoolSize, //核心线程池大小
int maximumPoolSize, //最大线程池大小
long keepAliveTime, //线程生存时间
TimeUnit unit, //时间单位
BlockingQueue<Runnable> workQueue, //任务队列
ThreadFactory threadFactory, //线程工厂
RejectedExecutionHandler handler) //异常处理器
接下来我们来解答问题:Java线程池中线程数量到底是几
线程池中的线程数量实际上是动态变化的,它由核心线程池大小(corePoolSize)、最大线程池大小(maximumPoolSize)、任务队列(workQueue)等参数共同决定。
具体来说,线程池中线程数量受以下几个条件制约:
-
当线程池中运行的线程数小于corePoolSize时,新加入的任务会创建一个新的线程来执行任务,并将该线程放入线程池中,因此线程池中运行的线程数就会增加。
-
当线程池中运行的线程数达到corePoolSize时,新加入的任务会被加入到任务队列(workQueue)中等待执行,在任务队列中等待的任务不会立即执行。
-
如果任务队列已满,且当前线程池中的线程数小于maximumPoolSize,则线程池会创建一个新的线程来执行任务,因此线程池中运行的线程数就会增加。
-
如果当前线程池中运行的线程数已经达到了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技术站