Java通过Executors提供四种线程池
ThreadPoolExecutor的执行流程
ThreadPoolExecutor的几个参数
corePoolSize:核心池的大小,这个参数跟后面讲述的线程池的实现原理有非常大的关系。在创建了线程池后,默认情况下,线程池中并没有任何线程,而是等待有任务到来才创建线程去执行任务,除非调用了prestartAllCoreThreads()或者prestartCoreThread()方法,从这2个方法的名字就可以看出,是预创建线程的意思,即在没有任务到来之前就创建corePoolSize个线程或者一个线程。默认情况下,在创建了线程池后,线程池中的线程数为0,当有任务来之后,就会创建一个线程去执行任务,当线程池中的线程数目达到corePoolSize后,就会把到达的任务放到缓存队列当中。
maximumPoolSize:线程池最大线程数,这个参数也是一个非常重要的参数,它表示在线程池中最多能创建多少个线程;如果当前阻塞队列满了,且继续提交任务,则创建新的线程执行任务,前提是当前线程数小于maximumPoolSize;当阻塞队列是无界队列,则maximumPoolSize不起作用,因为无法提交至核心线程池的线程会一直持续地放入workQueue(工作队列)中。
keepAliveTime:表示线程没有任务执行时最多保持多久时间会终止。默认情况下,只有当线程池中的线程数大于corePoolSize时,keepAliveTime才会起作用,直到线程池中的线程数不大于corePoolSize,即当线程池中线程数大于corePoolSize时,如果一个线程空闲的时间达到keepAliveTime,则会终止,直到线程池中的线程数不超过corePoolSize。但是如果调用了allowCoreThreadTimeOut(boolean)方法,在线程池中的线程数不大于corePoolSize时,keepAliveTime参数也会起作用,直到线程池中的线程数为0。
allowCoreThreadTimeout:默认情况下超过keepAliveTime的时候,核心线程不会退出,可通过将该参数设置为true,让核心线程也退出。
unit:可以指定keepAliveTime的时间单位。
workQueue
ArrayBlockingQueue有界队列,需要指定队列大小。
LinkedBlockingQueue若指定大小则和ArrayBlockingQueue类似,若不指定大小则默认能存储Integer.MAX_VALUE个任务,相当于无界队列,此时maximumPoolSize值其实是无意义的。
SynchronousQueue同步阻塞队列,当有任务添加进来后,必须有线程从队列中取出,当前线程才会被释放,newCachedThreadPool就使用这种队列。
RejectedExecutionHandler:线程数和队列都满的情况下,线程池会执行的拒绝策略,有四个(也可以使用自定义的策略)。
线程池的四种拒绝策略
Executors和ThreadPoolExecutor创建线程的区别
Executors
newFixedThreadPool和newSingleThreadExecutor:主要问题是堆积的请求处理队列可能会耗费非常大的内存,甚至OOM。
newCachedThreadPool和newScheduledThreadPool:主要问题是线程数最大数是Integer.MAX_VALUE(2的31次方-1,int类型最大值),可能会创建数量非常多的线程,甚至OOM。
ThreadPoolExecutor
创建线程池方式只有一种,就是走它的构造函数,参数自己指定。
为什么使用线程池
减少了创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务。
运用线程池能有效的控制线程最大并发数,可以根据系统的承受能力,调整线程池中工作线线程的数目,防止因为消耗过多的内存,而把服务器累趴下(每个线程需要大约1MB内存,线程开的越多,消耗的内存也就越大,最后死机)。
对线程进行一些简单的管理,比如:延时执行、定时循环执行的策略等,运用线程池都能进行很好的实现。
如何向线程池中提交任务
可以通过execute()或submit()两个方法向线程池提交任务。
execute()方法没有返回值,所以无法判断任务知否被线程池执行成功。
submit()方法返回一个future,那么我们可以通过这个future来判断任务是否执行成功,通过future的get方法来获取返回值。
如何关闭线程池
可以通过shutdown()或shutdownNow()方法来关闭线程池。
shutdown的原理是只是将线程池的状态设置成SHUTDOWN状态,然后中断所有没有正在执行任务的线程。
shutdownNow的原理是遍历线程池中的工作线程,然后逐个调用线程的interrupt方法来中断线程,所以无法响应中断的任务可能永远无法终止。shutdownNow会首先将线程池的状态设置成STOP,然后尝试停止所有的正在执行或暂停任务的线程,并返回等待执行任务的列表。
以上就是动力节点Java培训机构小编介绍的“程序员常见的Java线程池面试题”的内容,希望对大家有帮助,如有疑问,请在线咨询,有专业老师随时为你服务。
你适合学Java吗?4大专业测评方法
代码逻辑 吸收能力 技术学习能力 综合素质
先测评确定适合在学习