一、简介 什么是线程池 线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。...: schedule 方法可以在指定的延时后执行一个 Runnable 或者 Callable 任务。...此队列是基于数组的先进先出队列(FIFO)。 此队列创建时必须指定大小。 LinkedBlockingQueue - 无界阻塞队列。 此队列是基于链表的先进先出队列(FIFO)。...每次提交一个任务就会新创建一个工作线程,如果工作线程数量达到线程池最大线程数,则将提交的任务存入到阻塞队列中。...终止后,如果你又提交了新的任务,则线程池重新创建一个工作线程。 此线程池不会对线程池大小做限制,线程池大小完全依赖于操作系统(或者说 JVM)能够创建的最大线程大小。
(注意线程池的阻塞队列可以不设置长度的) 2....学术说明 来自百科的解释: 线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。线程池线程都是后台线程。...至于我们应该调用哪一种方法来关闭线程池,应该由提交到线程池的任务特性决定,通常调用shutdown来关闭线程池,如果任务不一定要执行完,则可以调用shutdownNow ---- 2....这个时候新的任务C,会挂在阻塞队列中,知道线程池中某个任务执行完毕,释放资源之后,任务C才会执行 简单来说,这个固定大小的线程池,就是线程池中的任务恒定为指定个数(即便空闲,也会有这么几个线程在);其他的任务都放在阻塞队列中执行...那么这儿有什么用 固定大小的线程池,保证同一时刻,最多只有n个任务在执行,所以可以有效的控制并发数 java.util.concurrent.Executors#newSingleThreadExecutor
当Worker对应的线程池启动时,它会执行线程池中的任务;当执行完一个任务后,它会从线程池的阻塞队列中取出一个阻塞的任务来继续运行。...该线程池中的线程数量始终不变,当有新任务提交时,线程池中有空闲线程则会立即执行,如果没有,则会暂存到阻塞队列。对于固定大小的线程池,不存在线程数量的变化。...在没有任务执行时,当线程的空闲时间超过keepAliveTime(60秒),则工作线程将会终止被回收,当提交新任务时,如果没有空闲线程,则创建新线程执行任务,会导致一定的系统开销。...在Java并发包里可阻塞方法都同时定义了限时方式和不限时方式。...在使用有界队列是,需要选择合适的拒绝策略,队列的大小和线程池的大小必须一起调节。
当maximumPoolSize的数量大于corePoolSize时,多的那部分空闲状态下的线程,会再超过一定时间后被销毁,只保留corePoolSize的核心线程数。...当线程池中线程数量达到corePoolSize时,且都处于运行状态,这时候后续提交的线程任务会进入到缓存阻塞队列中,等待执行。这个缓存阻塞队列也就是workQueue。...JUC中提供的BlockingQueue有以下几种: ArrayBlockingQueue:由数组实现的有界阻塞队列。需要指定队列的容量大小。当队列已满时,添加任务的操作将被阻塞,直到队列中有空位。...ArrayBlockingQueue适用于固定大小的线程池,可以控制线程池中的最大任务数。 LinkedBlockingQueue:由链表实现的可选有界或无界阻塞队列。...如果创建LinkedBlockingQueue时没有指定容量大小,那么它将是一个无界队列,可以无限制地添加任务。如果指定了容量大小,它将成为一个有界队列。当队列已满时,添加任务的操作将被阻塞。
该线程池中的线程数量始终不变,当有新任务提交时,线程池中有空闲线程则会立即执行,如果没有,则会暂存到阻塞队列。对于固定大小的线程池,不存在线程数量的变化。...,阻塞队列使用的是LinkedBlockingQueue,若有多余的任务提交到线程池中,则会被暂存到阻塞队列,待空闲时再去执行。...在没有任务执行时,当线程的空闲时间超过keepAliveTime(60秒),则工作线程将会终止被回收,当提交新任务时,如果没有空闲线程,则创建新线程执行任务,会导致一定的系统开销。...在Java并发包里可阻塞方法都同时定义了限时方式和不限时方式。...在使用有界队列是,需要选择合适的拒绝策略,队列的大小和线程池的大小必须一起调节。
在线程池中总有那么几个活跃的线程,也有一定的最大值限制,一个业务使用完线程之后,不是立即销毁而是将其放入到线程池中,从而实现线程的复用。...LinkedBlockingQueue 是一个由链表实现的有界队列阻塞队列,但大小默认值为Integer.MAX_VALUE整形数的最大值, 所以我们在使用LinkedBlockingQueue时建议手动传值...,为其提供我们所需的大小,避免队列过大造成机器负载或者内存爆满等情况。...SynchronousQueue 是一个没有容量,是无缓冲等待队列,是一个不存储元素的阻塞队列,会直接将任务交给消费者,必须等队列中的添加元素被消费后才能继续添加新的元素。...,而使用 get(long timeout,TimeUnit unit)方法则会阻塞当前线程一段时间后立即返回,这时候有可能任务没有执行完。
一、ArrayBlockingQueue概述 ArrayBlockingQueue是一个基于数组的有界阻塞队列。它在创建时需要指定队列的大小,并且这个大小在之后是不能改变的。...这种方式可以实现任务的异步执行和资源的有效利用。 四、最佳实践 合理设置队列大小:在使用ArrayBlockingQueue时,应根据实际需求合理设置队列的大小。...避免在队列中存储大量数据:由于ArrayBlockingQueue是基于数组的实现,每个元素都会占用一定的内存空间。因此,应避免在队列中存储大量数据,以减少内存消耗和垃圾回收的压力。...代码中模拟一个生产者线程生产数据,多个消费者线程消费数据的场景,并且消费者在处理完数据后会将结果存回另一个阻塞队列中以供后续处理。...最后,我们在主线程中等待生产者线程完成后,关闭消费者线程的ExecutorService,并处理resultQueue中的剩余数据。
认识线程池 关于“池”的概念,我们接触过字符串常量池,数据库连接池,它们都被用作共享和缓存资源,通俗的将就是使用的时候直接从池子里拿,线程池也一样,在初始化的时候,就创建一定数量元素,后面需要使用线程就直接从线程池中取...表示一个线程池实例 Executors 是一个工厂类, 能够创建出几种不同风格的线程池 提交任务到线程池中的阻塞队列中: execute(Runnable task) submit(Runnable...//创建有固定大小的线程池 ExecutorService pool2 = Executors.newFixedThreadPool(4); //创建有计划任务的线程池...pool4 = Executors.newSingleThreadExecutor(); ️注意:这种创建的方式在以后的工作中不建议用 在工作中要阻塞队列设置大小,如果不设置大小,在某个时间会导致内存不够...线程池的模拟实现 前提说明: 这里阻塞队列的实现采用链表的方式阻塞 我们要求线程池创建的时候,就创建线程不停的从队列中取任务来执行 这里创建5个员工 ️代码实现: import java.util.concurrent.BlockingDeque
0 unit 生存时间的单位时间 参考枚举类:java.util.concurrent.TimeUnit workQueue 工作线程队列 用于存放提交但是尚未被执行的任务 threadFactory...,否则一直put线程会一直阻塞(内部维护了一个Transferer 抽象类,提供了公平抢占消费&非公平抢占消费的实现); 超出基本大小的线程资源在一段时间后会被销毁,因此 keepAliveTime 设置为...总结: 好处:“无界限”的线程池,可以在资源被完全耗尽之前能够全力处理所有的任务提交(双刃剑); 弊端:由于最大线程池容量不设限,在提交任务极其频繁的条件下,可能会创建数量非常多的线程,甚至OOM。...C 如果 workerCount >= corePoolSize,且线程池内的阻塞队列未满(不阻塞),则将任务添加到该阻塞队列中。(基本大小满足了,还有临时工也在帮忙,再来单子得阻塞..)...所以,推荐一篇精品文章给大家自行阅读:《Java线程池实现原理及其在美团业务中的实践》。
; 如果等待队列已满,并且工作线程数 < maxPoolSize,则创建一个新线程来运行新任务,这个机制可能很多人都会搞错,这里就容易出现之前提交的任务还在等待队列中阻塞,但是新提交任务却被执行情况,千万注意...,提供了一些创建线程池方法,主要如下: ExecutorService newFixedThreadPool(int nThreads):创建一个固定大小、任务队列容量无界的线程池; ExecutorService...CompletionService对ExecutorService进行包装,将结果集按照完成时间的顺序放入到阻塞队列中,获取结果时只需要从阻塞队列中获取即可,即实现:先完成的任务先获取结果。...,CompletionService就是重写该方法,在FutureTask任务完成时添加到阻塞队列中去,这样就可以从阻塞队列中获取已完成的任务,见下: protected void done() { completionQueue.add...(task); } Tips:ExecutorCompletionService类中使用LinkedBlockingQueue无界队列存储结果集,所以,一定要及时去取结果,不然完成的任务结果不停的堆积到阻塞队列中
1,按阻塞队列和非阻塞队列划分为两类 1、没有实现的阻塞接口的LinkedList: 实现了java.util.Queue接口和java.util.AbstractQueue接口 内置的不阻塞队列...收集关于队列大小的信息会很慢,需要遍历队列。...使用非阻塞队列的时候有一个很大问题就是:它不会对当前线程产生阻塞,那么在面对类似消费者-生产者的模型时,就必须额外地实现同步策略以及线程间唤醒策略,简单理解就是非阻塞队列时,一个线程去拿队列里的东西,发现这个队列是空的...当队列中有元素后,被阻塞的线程会自动被唤醒(不需要我们编写代码去唤醒),也就是始终有个线程在等着这个队列,如果队列中有东西了,被阻塞的线程会主动去拿。这样提供了极大的方便性。...3)在步骤2)中新创建的线程将任务执行完后,会执行 SynchronousQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS)。
线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。 为什么要用线程池? 降低资源消耗 通过重复利用已创建的线程降低线程创建和销毁造成的消耗。...默认情况下,在创建了线程池后,线程池中的线程数为 0,当有任务来之后,就会创建一个线程去执行任务,当线程池中的线程数目达到 corePoolSize 后,就会把到达的任务放到缓存队列当中。...workQueue:任务队列。用于保存等待执行的任务的阻塞队列。 可以选择以下几个阻塞队列。...在使用 CachedThreadPool 时,一定要注意控制任务的数量,否则,由于大量线程同时运行,很有会造成系统瘫痪。...:基于链表的先进先出队列,如果创建时没有指定此队列大小,则默认为 Integer.MAX_VALUE; SynchronousQueue:这个队列比较特殊,它不会保存提交的任务,而是将直接新建一个线程来执行新来的任务
最大线程数:线程池中允许的最大线程数。 存活时间:非核心线程在没有任务执行时的存活时间。 时间单位:与存活时间配合使用的时间单位。 工作队列:存储等待执行任务的阻塞队列。...LinkedBlockingQueue:一个由链表结构组成的有界阻塞队列。 SynchronousQueue:一个不存储元素的阻塞队列,即直接提交给线程不保持它们。...DelayQueue:一个使用优先级队列实现的无界阻塞队列,只有在延迟期满时才能从中提取元素 LinkedTransferQueue:一个由链表结构组成的无界阻塞队列。...在Java的线程池中,submit() 和 execute() 是两种不同的方法,它们都用于向线程池提交任务。...在示例代码中,我们首先使用schedule方法提交了一个延迟2秒后执行的单次任务。
而且任务队列最好也要有容量,但也应该是根据业务场景来配置容量,而且任务队列还可以定制一些规则,例如:按照一定的规则出队。所以我们把任务队列也配置成参数,在创建线程池的时候传入。...下面说几个线程池常见的考察点 Java中的线程池的阻塞队列都有哪几种 ArrayBlockingQueue : 有界队列,按照阻塞的先后顺序访问队列,默认情况下不保证线程公平的访问队列~如果要保证公平性...在不允许任务在队列中等待的时候可以使用此队列。 DelayQueue:延迟获取元素队列,按照指定时间后获取,为无界阻塞队列。...PriorityBlockingQueue:优先级排序队列,按照一定的优先级对任务进行排序,默认是小顶堆。 LinkedBlockingDeque:基于链表的双端阻塞队列。...,并且阻塞任务队列还是一个无解队列,这样,当处理任务的线程数量达到核心线程数时,再提交的任务都会进行到阻塞队列里,但是阻塞队列是无界的,这样就提交任务高峰期有可能会造成任务一直堆积在队列里,超出内存容量最终导致内存溢出
异常场景2 产生RejectedExecutionException异常第二个原因: 要提交给阻塞队列的任务超出了该队列的最大容量。...当线程池里的线程都繁忙的时候,新任务会被提交给阻塞队列保存,这个阻塞队列一旦饱和,线程池就会拒绝接收新任务,随即抛出异常。...,运行之后抛异常 } } 在上面的例子中,我们使用了一个大小为15的ArrayBlockingQueue阻塞队列来保存等待执行的任务。...我们可以选择一种不需要设置大小限制的数据结构,比如LinkedBlockingQueue阻塞队列。...其实我们可以给使用ArrayBlockingQueue作为阻塞队列的ThreadPoolExecutor线程池提交超过15个的任务,只要我们在提交新任务前设置一个完成原来任务的等待时间,这时3个线程就会逐渐消费
线程池的工作流程主要包括以下几个步骤: 创建线程池:初始化时,预先创建一定数量的线程并将其置于待命状态,等待任务分配。 任务提交:当有新任务到达时,将其加入到任务队列中。...workQueue:任务队列 用于保存等待执行的任务的阻塞队列。...----------------队列阻塞的线程数3 活跃的线程数: 5 ----------------队列阻塞的线程数4 活跃的线程数: 5 ----------------队列阻塞的线程数5 活跃的线程数...: 6 ----------------队列阻塞的线程数5 活跃的线程数: 7 ----------------队列阻塞的线程数5 活跃的线程数: 8 ----------------队列阻塞的线程数5...threadPool.shutdown(); } 通过这样的调整,当线程池和队列达到饱和状态后,任何新提交的任务将被默默地丢弃,这种方式适用于那些可以安全丢弃的任务场景,避免了因任务拒绝而引发的异常中断
二、线程池的体系结构及工具类 1、线程池的体系结构 Java.util.concurrent.Executor : 负责线程的使用与调度的根接口 |-- ExecutorService...,具备两者的功能 2、Executors工具类 ExecutorService new FixedThreadPool() : 创建固定大小的线程池 ExecutorService newCachedThreadPool...如果允许任务丢失,这是最好的一种方案。 3、以上内置拒绝策略均实现了RejectedExecutionHandler接口 五、线程池的底层工作原理? 1、在创建了线程池后,等待提交过来的任务请求。...所以线程池的所有任务完成后它最终会收缩到corePoolSize的大小。...在单线程上运行IO密集型的任务会导致浪费大量的CPU运算能力浪费在等待。 所以IO密集型任务中使用多线程可以大大的加速程序运行,即使在单核CPU上,这种加速主要就是利用了被浪费掉的阻塞时间。
提交任务 ExecutorService:接口 继承Executor接口 增加了submit提交任务的方式(有返回值) 以及关闭 操作 AbstractExecutorService实现了ExecutorService...maximumPoolSize 最大线程池大小 keepAliveTime 空闲线程的存活时间 unit 空闲线程保持存活的时间的单位 workQueue 阻塞任务队列,当要执行的任务超出corePoolSize...时,新提交的任务将会进入阻塞队列(workQueue)中,等待线程的调度 当阻塞队列满了以后,如果corePoolSize < maximumPoolSize ,则新提交的任务会新建线程执行任务,直至线程数达到...threadPoolExecutor.shutdown(); } } 输出结果: pool-1-thread-1 main pool-1-thread-1 分析一下:因为核心线程池+ 阻塞队列的大小...当提交第一个任务时,新建线程执行任务,当提交第二个任务时,由于线程池的核心大小为1并且有任务在执行,放入阻塞队列,当提交第三个任务,发现阻塞队列已经满了,而且线程池的最大的线程个数也达到了最大。
Java并发容器和框架 Java中的12个原子操作类介绍 Java中的并发工具类 Java中的线程池 Executor框架 ---- 前言 在Java中,使用线程来异步执行任务。...Java线程的创建与销毁需要一定的开销,如果我们为每一个任务创建一个新线程来执行,这些线程的创建与销毁将消耗大量的计算资源。...但从API可以看到,Java仅仅保证返回的是一个实现了Future接口的对象。在将来的JDK实现中,返回的可能不一定是FutureTask。...AQS是一个同步框架,它提供通用机制来原子性管理同步状态、阻塞和唤醒线程,以及维护被阻塞线程的队列。...这个操作改变AQS的状态,改变后的状态可允许一个或多个阻塞线程被解除阻塞。FutureTask的release操作包括run()方法和cancel(...)方法。
当队列满了后,还有执行任务进入时的策略 workQueue参数需要传入一个BlockingQueue,这是个双缓冲队列。...在保证并发安全的同时,提高了队列的存取效率,不能传入空对象,可设置容量大小,也可以不设置容量大小,那么它的容量就是Integer.MAX_VALUE。...常用的几种实现类 类 说明 ArrayBlockingQueue 规定容量大小的阻塞队列 LinkedBlockingQueue 既可以规定容量大小,也可以不规定的阻塞队列 SynchronizedQueue...一个特殊的队列,生产消费必须交替完成的队列生产一个元素后,必须要有进行消费后,才能继续往队列内生产元素 handler拒绝策略 当线程池指定的队列容量满了时,将执行哪种拒绝任务的策略 策略类 说明...比如说addWorker方法,线程池的执行调度等 后续有什么新的理解继续补上,未完待续 关于本文出现的代码示例,已提交至码云,只看文章不懂时,一定要敲代码进行理解。 我是半月,祝你幸福!
领取专属 10元无门槛券
手把手带您无忧上云