如何设置线程池参数
假设:
每秒任务数 tasks per second. tasks = 1000 t / s
最大每秒任务数 max tasks per second maxTasks = 3000 t / s
每个任务花费时间 task cost time costTime = 0.1s
系统容许最大响应时间 max response time maxTime = 2s
corePoolSize = tasks / (1 / costTime) = 1000 * 0.1 = 100
queueCapacity = corePoolSize / costTime * maxTime = 100 / 0.1 * 2 = 2000
maxPoolSize = (maxTasks - queueCapacity) / (1 / costTime) = (3000 - 2000) * 10 = 10000
线程池中为什么要使用阻塞队列?
如果新任务的到达速率超过了线程池的处理速率,那么新到来的请求将累加起来,这样的话将耗尽资源。
线程池创建线程需要获取mainlock这个全局锁,影响并发效率,阻塞队列可以很好的缓冲。
corePoolSize设置为0会怎么样?
如果添加队列成功,判断当前池内线程数是否为0,如果是则创建一个firstTask为null的worker,这个worker会从等待队列中获取任务并执行。
如果添加到等待队列失败,一般是队列已满,才会再尝试创建新的线程。
线程池创建之后,会立即创建核心线程么?
在刚刚创建ThreadPoolExecutor的时候,线程并不会立即启动,而是要等到有任务提交时才会启动,除非调用了prestartCoreThread/prestartAllCoreThreads事先启动核心线程。
核心线程永远不会销毁么?
从JDK1.6开始,提供了方法allowsCoreThreadTimeOut,如果传参为true,则允许闲置的核心线程被终止。
空闲线程过多会有什么问题?
会占用内存
-虚拟机栈
-本地方法栈
-程序计数器
-ThreadLocal
-局部变量
-TLAB
shutdown和shutdownNow的区别
shutdown => 平缓关闭,等待所有已添加到线程池中的任务执行完再关闭。
shutdownNow => 立刻关闭,停止正在执行的任务,并返回队列中未执行的任务。
一个线程池中的线程异常了,那么线程池会怎么处理这个线程?
-当执行方式是execute时,可以看到堆栈异常的输出。也可以通过setUncaughtExceptionHandler指定处理异常。
-当执行方式是submit时,堆栈异常没有输出。但是调用Future.get()方法时,可以捕获到异常。
-不会影响线程池里面其他线程的正常执行。
-线程池会把这个线程移除掉,并创建一个新的线程放到线程池中。