使用线程池的好处
降低资源消耗,提高响应速度,提高线程的可管理性
Executor框架简介
Executor框架是Java5之后引进的,在Java5之后通过Executor来启动线程比使用Thread的start方法更好,使用线程池,节约开销,有助于避免this逃逸问题。
Executor框架不仅包括线程池的管理,还提供线程工厂、队列以及拒绝策略等,Executor框架让并发编程变得更加简单。
Executor框架结构(主要由三大部分组成)
任务(Runnable/Callable)
执行任务需要实现的Runnable接口或Callable接口。Runnable接口或Callable接口实现类可以被ThreadPoolExecutor或ScheduledThreadPoolExecutor执行。
任务的执行(Executor)
任务执行的核心接口Executor,以及继承字Executor接口的ExecutorService接口。ThreadPoolExecutor和ScheduledThreadPoolExecutor这两个关键类实现了ExecutorService接口。
ThreadPoolExecutor这个类在我们实际使用线程池的过程中,使用频繁非常高。
通过查看ScheduledThreadPoolExecutor线程池的源码我们发现ScheduledThreadPoolExcutor实际上是继承了ThreadPoolExecutor并实现了ScheduledExecutorService,而ScheduledExecutorService又实现了ExecutorService
3)异步计算的结果(Future)
Future接口以及Future接口的实现类FutureTask类都可以代表异步计算的结果
当我们把Runnable接口或Callable接口的实现类提交给ThreadPoolExecutor或ScheduledThreadPoolExecutor执行。(调用submit()方法时会返回一个FutureTask对象)
主线程首先要创建Runnable或者Callable接口的任务对象。
把创建的实现Runnabe/Callable接口的对象直接交给ExecutorServic.execute方法,也可以把Runable对象或者Callable对象提交给ExecutorService.submit方法
如果执行ExecutorService.submit(),ExecutorServicce将返回一个实现Future接口的对象,submit()我们可以创建FutureTask,然后直接交给ExecutorService执行。
最后,主线程可以执行FutureTask.get()方法来等待任务执行完成。主线程可以执行FutureTask.cancel()来取消此任务的执行
ThreadPoolExecutor类简单介绍
线程池ThreadPoolExecutor是Executor框架最核心的类
ThreadPoolExecutor类构造方法
int corePoolSize 线程池的核心线程数
int maximumPoolSize 线程池的最大线程数
long keepAliveTime 当线程数大于核心数时,多余的空闲线程存活的最长时间
TimeUnit 时间单位
BlockingQueue
ThreaFactory threadFactory线程工厂,用来创建线程,一般默认即可
RejectedExecutionHandler 拒绝策略,当提交的任务过多的时候,我们定制策略来处理
ThreadPoolExecutor饱和策略定义:
如果当前同时运行的线程数量达到了最大线程数量并且队列也被放满了任务时,ThreadPoolTaskExecutor定义了一些策略
AbortPolicy抛出RejectedExecutionException来拒绝新任务的处理。
ThreadPoolExecutor.CallerRunsPolicy:调用执行自己的线程运行任务。如果你的应用程序可以承受此延迟并且你不能任务丢弃任何一个任务请求的话,你可以选择这个策略
DiscardPlolicy:不处理新任务,直接丢弃掉。
DiscardOldestPolicy:此策将丢弃最早的未处理的任务请求。