干货,一篇文章搞懂Java线程池所有问题,学习Java线程池知识点,没搞懂的小伙伴,可以仔细阅读,对理解Java线程池有极大的帮助。
1、如何实现Java中的线程池?
在Java中的线程池的“线程”,就是被抽象成了一个静态内部类Worker,它是基于AQS实现,存储在线程池的HashSetworkers成员变量中而需要执行的任务,因此存放在成员变量workQueue中。为此,整个线程池实现的底层思想就是:从workQueue中一直取出需要执行的任务,放在Workers中进行处理。如需要执行的任务需要存放在成员变量里。
2、创建线程池有几个构造参数?
Java中的线程池的创建灵活,可以通过不同的参数进行配置,创建出任务不同的线程池,参数如下:
CorePoolSize:线程池的核心线程数
MaximumPoolSize:线程池允许的最大线程数
KeepAliveTime:超过核心线程数时闲置线程的存活时间
workQueue:任务执行前保存任务队列,保存由execute方法进行提交的Runnable任务。
3、线程池中的线程是怎么创建的?一开始就随着线程池的启动创建吗?
当然不是。初始化后不启动Worker是默认的线程池,只有当有请求时才会启动。每当调用execute()方法添加任务时,线程池会做出以下判断:。
如果正在运行的线程数小于corePoolSize,则立即创建一个线程来运行此任务。
如果正在运行的线程数大于或等于corePoolSize,则将此任务放入队列中。
如果此时队列已满,并且正在运行的线程数小于maximumPoolSize,那么仍然需要创建一个非核心线程来立即运行任务。
如果队列已满,且正在运行的线程数大于或等于maximumPoolSize,则线程池将抛出异常。
返回执行异常。当一个线程完成一个任务时,它会从队列中取出下一个任务来执行。当一个。
线程无事可做,当它超过一定时间(keepAliveTime)时,线程池将判断。
如果当前正在运行的线程数大于corePoolSize,则此线程将被停止。因此,在线程池的所有任务完成后,它最终将缩小到corePoolSize的大小。
4、既然提到可以通过配置不同参数创建出不同的线程池,那么Java中默认实现好的线程池又有哪些呢?请比较它们的异同。
1.SingleThreadExecutor线程池这个线程池只有一个核心线程在工作,这相当于用一个线程串行地执行所有任务。在。如果唯一的线程异常结束,则会有一个新的线程替换它。。这个线程池保证所有任务的执行顺序按照提交任务的顺序执行。
corePoolSize:1,只有一个核心线程在工作
maximumPoolSize:1
keepAliveTime:0L
workQueue:newLinkedBlockingQueue(),其缓冲队列是无界的。
2.FixedThreadPool线程池FixedThreadPool是一个只有核心线程的固定大小线程池。每次提交任务时创建一个线程,直到线程达到线程池的最大大小。一旦线程池的大小达到极大值,它将保持不变。如果一个线程由于执行异常而结束,线程池将添加一个新的线程。FixedThreadPool主要针对一些非常稳定和固定的常规并发线程,主要用于服务器。
corePoolSize:nThreads
maximumPoolSize:nThreads
keepAliveTime:0L
workQueue:newLinkedBlockingQueue(),其缓冲队列是无界的。
3.CachedThreadPool线程池CachedThreadPool是一个无界线程池。如果线程池的大小超过了处理任务所需的线程,那么将回收一些空闲线程(60秒内未执行任务)。当任务数量增加时,这个线程池可以智能地添加新线程来处理任务。线程池的大小完全取决于操作系统(或JVM)可以创建的最大线程大小。SynchronousQueue是一个阻塞队列,缓冲区为1。缓存型池子通常用于执行一些生存期很短的异步型任务,因此在一些面向连接的daemon型SERVER中用得不多。但对于短命的异步任务,它是Executor的首选。
corePoolSize:0
maximumPoolSize:Integer.MAX_VALUE
keepAliveTime:60L
workQueue:newSynchronousQueue(),一个是缓冲区为1的阻塞队列。
4.ScheduledThreadPool线程池ScheduledThreadPool:核心线程池固定,大小无限的线程池。此线程
池支持定时以及周期性执行任务的需求。创建一个周期性执行任务的线程池。如果闲置,非核心线程池会在DEFAULT_KEEPALIVEMILLIS时间内回收。
corePoolSize:corePoolSize
maximumPoolSize:Integer.MAX_VALUE
keepAliveTime:DEFAULT_KEEPALIVE_MILLIS
workQueue:newDelayedWorkQueue()
5、如何在Java线程池中提交线程?
线程池最常用的提交任务的方法有两种:
1.execute():ExecutorService.execute方法接收一个Runable实例,它用来执行一个任务:
2.submit():ExecutorService.submit()方法返回的是Future对象。可以用isDone()来查询Future是否已经完成,当任务完成时,它具有一个结果,可以调用get()来获取结果。也可以不用isDone()
进行检查就直接调用get(),在这种情况下,get()将阻塞,直至结果准备就绪。
Java如何入门
Java300集的学习路线图完整版
根据学习线路学习,这套教程是专门为零基础的学生制作的。它适合于零基础的准备开始Java开发的学生。视频中穿插了许多实用的项目。每一个知识点都以浅显易懂的方式讲解,由浅入深。
不仅适合零基础初学者,有经验的程序员也可以做巩固学习。
领取专属 10元无门槛券
私享最新 技术干货