什么是线程池?
线程池就是事先将多个线程对象放到一个容器中,当使用的时候就不用再创建了,直接去池中拿就可以了。这样节省了开辟子线程的时间,提高了代码执行效率。
如何使用?
在JDK的java.util.concurrent.Executors中提供了生成多种线程池的静态方法。
ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(4);
ScheduledExecutorService newScheduledThreadPool = Executors.newScheduledThreadPool(4);
ExecutorService newSingleThreadExecutor = Executors.newSingleThreadExecutor();
然后调用它们的execute()方法即可。
常用有四种:
FixedThreadPool 线程数量固定,且只有核心线程,无超时时间。线程处于空闲的时候,并不会被回收,除非线程池被关闭。
CachedThreadPool 只有非核心线程,且最大线程数为Integer.MAX_VALUE。当线程池中所有线程都处于活动的状态时,线程池会创建新的线程来处理新任务,否则就会复用空闲线程来处理。
SingleThreadPool 只有一个核心线程,并且无超时时间。
ScheduledThreadPool 核心线程数是固定的,非核心线程无限大,并且非核心线程数有10S的空闲存活时间。这个线程池主要用于执行定时任务 和 具有固定周期的重复任务。
合理利用线程池有三个好处:
第一:降低资源消耗。通过重复利用已创建的线程降低线程创建 和 销毁造成的消耗。
第二:提高响应速度。当任务到达时,任务可以不需要等到线程创建就能直接执行。
第三:提高线程的可管理性。使用线程池可以对线程进行统一分配,调优 和 监控。
线程池的启动策略
1、线程池刚创建时,里面没有一个线程。任务队列 是作为参数传进来的。不过,就算队列里有任务,线程池也不会马上执行。
2、当调用execute() 方法添加一个任务时,线程池会做如下判断:
a.如果正在运行的线程数量 小于 corePoolSize,那么马上创建线程执行这个任务;
b.如果正在运行的线程数量大于 或 等于 corePoolSize,那么将这个任务放入队列;
c.如果队列满了,而且正在运行的线程数量小于 maximumPoolSize,那么还是要创建线程运行这个任务;
d.如果队列满了,而且正在运行的线程数大于 等于 maximumPoolSize,那么线程池会抛出异常,说明"我不能再接受任务了";
3、当一个线程完成任务时,它会从队列中取 下一个任务 来执行;
4、当一个线程无事可做,超过一定时间 (keepAliveTime)时,线程池会判断, 如果当前运行的线程数大于 corePoolSize,那么这个线程就会被停掉。所以线程池的所有任务完成后,它最终会收缩到 corePoolSize 的大小。
描述一下对线程池的理解
对这个问题,可以从线程池是什么,怎么使用,好处,启动策略这几个方面来介绍。