原理
Executor
- 执行者,顶层接口
- 线程池从功能上看就是一个任务执行器
- ThreadPoolExecutor提交任务逻辑
- 判断corePoolSize,如果没到则新建,并标记为核心线程
- 如果达到corePoolSize,则加入workQueue
- 判断maximumPoolSize,如果超过执行拒绝策略处理器RejectedExecutionHandler ```java void execute(Runnable command); // 无返回值,主线程不能捕获异常 Future<?> submit(Runnable task); // 有返回值,主线程可以捕获异常
<a name="KVlvG"></a>## ExecutorService- 接口API- 启动- 关闭等```javavoid execute(Runnable command); // 无返回值,主线程不能捕获异常void shutdown(); // 停止接收新任务,原来的任务继续执行List<Runnable> shutdownNow(); // 立即关闭,包括原来的任务awaitTermination(long timeOut, TimeUnit unit); // 当前线程阻塞
ThreadFactory
线程工厂
工具类
-
Callable
Runnable#run()没有返回值
Callable#call()有返回值
public class RandomSleepTask implements Callable<Integer>{ @Override public Integer call() throws Exception{ Integer sleep = new Random().nextInt(10000); TimeUnit.MILLISECONDS.sleep(sleep); return sleep; } }Future
线程池参数
缓冲队列
BlockingQueue是双缓冲队列,内部使用两条队列,允许两个线程同时向队列存储、取出,保证并发安全的同时,提高了队列的存取效率
ArrayBlockingQueue:规定大小的BQ,其构造必须指定大小,所含的对象是FIFO顺序排序的
- LinkedBlockingQueue:大小不固定的BQ,若其构造时指定大小,生成的BQ有大小限制,不指定大小则有Integer.MAX_VALUE来决定,所含的对象是FIFO顺序排序的
- PriorityBlockingQueue:类似于LinkedBlockingQueue,但是所含对象的排序不是FIFO,而是依据构造函数的Comparator或自然顺序决定
SynchronizedQueue:特殊的BQ,对其操作必须是放和取交替完成
拒绝策略
ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常,默认策略
- ThreadPoolExecutor.DiscardPolicy:丢弃任务,但是不抛出异常
- ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新提交被拒绝的任务
ThreadPoolExecutor.CallerRunsPolicy:由调用线程(提交任务的线程)处理该任务
线程工厂
public class CustomThreadFactory implements ThreadFactory{ private AtomicInteger serial = new AtomicInteger(0); @Override public Thread newThread(Runnable r){ Thread thread = new Thread(r); thread.setDaemon(true); //根据需要 thread.setName("CustomThread-"+serial.getAndIncrement()); return thread; } }创建线程池方法
newSingleThreadExecutor
- 创建一个单线程的线程池,其实就是单线程串行执行所有任务保,证所有的执行顺序按照提交顺序依次执行
- 如果这个线程异常结束,那么就会有一个新的线程来替代它
- newFixedThreadPool
- 创建固定大小的线程池
- 每次提交一个任务就创建一个线程,直到最大大小,达到最大值后就会保持不变
- 如果某个线程因为异常而结束,那么线程池就会补充一个新线程
- 创建固定线程池的经验
- 不是越大越好,太小肯定也不好,假设核心数是N
- 如果是CPU密集型,则线程池大小设置为N或N+1
- 如果是IO密集型,则线程池大小设置为2N或2N+2
- newCachedThreadPool
- 创建一个可缓存的线程池
- 如果大小超过了处理任务需要的线程就会回收部分空闲(60s不执行)的线程
- 当任务数增加时,又可以智能的增加新线程来处理任务
- 不会对线程池大小做限制,完全依赖于JVM能够创建的最大线程大小
- newScheduledThreadPool
- 创建一个大小无限的线程池
- 支持定时以及周期性的执行任务的需求
