线程池的原理和基本使用~

简介: 线程池的原理和基本使用~

线程池的基本原理:

无论是之前在JavaSE基础中,我们学习过的常量池,还是在操作数据库时,我们学习过数据库连接池,以及接下来要学习的线程池,均是一种池化思想,其目的就是为了提高资源的利用率,线程池顾名思义就是对线程对象的一种优化,如果不使用线程池,那么我们对线程的操作即为手动创建线程对象,执行任务,任务执行完毕,释放线程对象,映射到我们生活为我们每次打电话都需要买一个手机,每次打完电话就将手机扔掉,那么这样一来,无疑是非常的铺张浪费,而线程池就类似于将手机重复利用而不是每次都换新的,它能很好地提高资源的利用率,并且由于线程对象是提前创建好的,因此也能够提高程序的响应速度。


下面我使用日常生活中最常见的一个例子来说明线程池的原理


我们可以将海底捞作为一个线程池,那么海底捞中的桌子可以看作是线程对象,假设当前店中已经有3张空闲的桌子可以使用,此时来了4组客人需要吃饭,那么服务员会根据先后顺序先安排前3组客人进行就餐,剩下的一组客人需要进入等待区,随后来的客人都会进入等待区,但是等待区的位置也不是无穷无尽的啊,假设我们的等待区只能最多让2个用户进行等待,当前如果又来了一个客人,那么就会出现他们既没有空闲的餐桌供他们使用,等待区也没有空闲的位置,那么此时由于客人并发量太大了,海底捞的老板就会触发一种应急方案,就是在当前餐厅空旷的区域加桌子,那么等待区中的第一位客人就可以从等待区中出来了呀,刚刚没有办法处理的客人此时就可以加入等待区中,加桌子是挺好的,但是也不能无限加啊,因为餐厅可使用的地方是有限的,当达到最大值后,又来了一位客人,那么服务员只好拒绝接待该客人!


使用Java简单模拟实现线程池:

package org.example;
import java.util.concurrent.*;
public class Main {
    public static void main(String[] args) {
        //3-->表示核心的线程对象数量,也就是上述海底捞例子中没加桌子前的餐厅桌子数量
        //5-->表示最大线程对象的数量,也就是上述海底捞例子中该餐厅最多可容纳的桌子数量
        //1和后面的TimeUnit.SECONDS表示1秒钟没有任务,就可以停止工作了
        //ArrayBlockingQueue-->表示一个等待队列
        //defaultThreadFactory-->调用默认的工厂
        //AbortPolicy拒绝策略
        //ExecutorService是Java提供的线程池
        ExecutorService executorService=new ThreadPoolExecutor(3,5,1L, TimeUnit.SECONDS,new ArrayBlockingQueue<>(3), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
        for (int i=0;i<9;i++){
            executorService.execute(()->{
                System.out.println(Thread.currentThread().getName()+"办理业务");
            });
        }
        executorService.shutdown();
    }
}

输出如下所示:

当前线程池最多可容纳线程的数量为8,那么到第九个线程就会触发拒绝策略

pool-1-thread-1办理业务
pool-1-thread-5办理业务
pool-1-thread-4办理业务
pool-1-thread-3办理业务
pool-1-thread-2办理业务
pool-1-thread-4办理业务
pool-1-thread-1办理业务
pool-1-thread-5办理业务
Exception in thread "main" java.util.concurrent.RejectedExecutionException: Task org.example.Main$$Lambda$1/1283928880@682a0b20 rejected from java.util.concurrent.ThreadPoolExecutor@3d075dc0[Running, pool size = 5, active threads = 5, queued tasks = 3, completed tasks = 0]
  at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2063)
  at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:830)
  at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1379)
  at org.example.Main.main(Main.java:15)
相关文章
|
4月前
|
安全 Java 数据库
一天十道Java面试题----第四天(线程池复用的原理------>spring事务的实现方式原理以及隔离级别)
这篇文章是关于Java面试题的笔记,涵盖了线程池复用原理、Spring框架基础、AOP和IOC概念、Bean生命周期和作用域、单例Bean的线程安全性、Spring中使用的设计模式、以及Spring事务的实现方式和隔离级别等知识点。
|
4月前
|
编解码 网络协议 API
Netty运行原理问题之Netty的主次Reactor多线程模型工作的问题如何解决
Netty运行原理问题之Netty的主次Reactor多线程模型工作的问题如何解决
|
3月前
|
存储 缓存 Java
什么是线程池?从底层源码入手,深度解析线程池的工作原理
本文从底层源码入手,深度解析ThreadPoolExecutor底层源码,包括其核心字段、内部类和重要方法,另外对Executors工具类下的四种自带线程池源码进行解释。 阅读本文后,可以对线程池的工作原理、七大参数、生命周期、拒绝策略等内容拥有更深入的认识。
144 29
什么是线程池?从底层源码入手,深度解析线程池的工作原理
|
2月前
|
Java 编译器 程序员
【多线程】synchronized原理
【多线程】synchronized原理
61 0
|
2月前
|
Java 应用服务中间件 API
nginx线程池原理
nginx线程池原理
37 0
|
3月前
|
存储 缓存 Java
JAVA并发编程系列(11)线程池底层原理架构剖析
本文详细解析了Java线程池的核心参数及其意义,包括核心线程数量(corePoolSize)、最大线程数量(maximumPoolSize)、线程空闲时间(keepAliveTime)、任务存储队列(workQueue)、线程工厂(threadFactory)及拒绝策略(handler)。此外,还介绍了四种常见的线程池:可缓存线程池(newCachedThreadPool)、定时调度线程池(newScheduledThreadPool)、单线程池(newSingleThreadExecutor)及固定长度线程池(newFixedThreadPool)。
|
4月前
|
存储 NoSQL Java
线程池的原理与C语言实现
【8月更文挑战第22天】线程池是一种多线程处理框架,通过复用预创建的线程来高效地处理大量短暂或临时任务,提升程序性能。它主要包括三部分:线程管理器、工作队列和线程。线程管理器负责创建与管理线程;工作队列存储待处理任务;线程则执行任务。当提交新任务时,线程管理器将其加入队列,并由空闲线程处理。使用线程池能减少线程创建与销毁的开销,提高响应速度,并能有效控制并发线程数量,避免资源竞争。这里还提供了一个简单的 C 语言实现示例。
|
4月前
|
存储 Java
线程池的底层工作原理是什么?
【8月更文挑战第8天】线程池的底层工作原理是什么?
119 8
|
3月前
|
安全 Java API
Java线程池原理与锁机制分析
综上所述,Java线程池和锁机制是并发编程中极其重要的两个部分。线程池主要用于管理线程的生命周期和执行并发任务,而锁机制则用于保障线程安全和防止数据的并发错误。它们深入地结合在一起,成为Java高效并发编程实践中的关键要素。
33 0
|
5月前
|
监控 Java 开发者
深入理解Java并发编程:线程池的原理与实践
【5月更文挑战第85天】 在现代Java应用开发中,高效地处理并发任务是提升性能和响应能力的关键。线程池作为一种管理线程的机制,其合理使用能够显著减少资源消耗并优化系统吞吐量。本文将详细探讨线程池的核心原理,包括其内部工作机制、优势以及如何在Java中正确实现和使用线程池。通过理论分析和实例演示,我们将揭示线程池对提升Java应用性能的重要性,并给出实践中的最佳策略。