Executors
Executors为Executor,ExecutorService,ScheduledExecutorService,ThreadFactory和Callable类提供了一些工具方法,类似于集合中的Collections类的功能
- newCachedThreadPool
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
功能:它将会为每个任务创建一个线程,此线程池的最大值是Integer的最大值(2^31-1),60秒内可以重用已经创建的线程,如果线程池的大小超过了处理任务所需要的线程,那么就会回收部分空闲的线程
适用:该线程池比较适合没有固定大小并且比较快速就能完成的小任务
- newFixedThreadPool
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
功能:创建固定大小的线程池。每次提交一个任务就创建一个线程,直到线程达到线程池的最大大小。线程池的大小一旦达到最大值就会保持不变,再提交新任务,任务将会进入等待队列中等待。如果某个线程因为执行异常而结束,那么线程池会补充一个新线程
- newSingleThreadExecutor
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
功能:创建一个单线程的线程池。也就是相当於单线程串行执行所有任务。如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代,。此线程池保证所有任务的执行顺序按照任务的提交顺序执行
除了CachedThreadPool使用的是直接提交策略的缓冲队列以外,其余两个采用的都是无界缓冲队列
以上三种都使用ThreadPoolExecutor创建
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
threadFactory, defaultHandler);
}
private static final RejectedExecutionHandler defaultHandler =
new AbortPolicy();
corePoolSize:核心线程数量,小于corePoolSize都会直接创建线程
maximumPoolSize:最大线程数量,大于最大线程数量则由拒绝策略处理
keepAliveTime:线程最大空闲存活时间
unit:线程最大空闲存活时间单位
workQueue:缓冲队列,超过任务超过corePoolSize大小后,放入workQueue队列进行缓冲处理
threadFactory:线程工厂
defaultHandler:拒绝处理程序策略 默认AbortPolicy 抛出异常
拒绝处理程序策略
默认的ThreadPoolExecutor.AbortPolicy
处理程序遭到拒绝将抛出运行时RejectedExecutionException;
public static class AbortPolicy implements RejectedExecutionHandler {
public AbortPolicy() { }
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
throw new RejectedExecutionException("Task " + r.toString() +
" rejected from " +
e.toString());
}
}
ThreadPoolExecutor.CallerRunsPolicy
调用excute任务本身的线程处理,主线程直接调用,如果执行程序已关闭,则会丢弃该任务
public static class CallerRunsPolicy implements RejectedExecutionHandler {
public CallerRunsPolicy() { }
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
r.run();
}
}
ThreadPoolExecutor.DiscardPolicy
不能执行的任务将被删除;
public static class DiscardPolicy implements RejectedExecutionHandler {
public DiscardPolicy() { }
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
}
}
ThreadPoolExecutor.DiscardOldestPolicy
如果执行程序尚未关闭,则位于工作队列头部的任务将被删除,然后重试执行程序(如果再次失败,则重复此过程)。
public static class DiscardOldestPolicy implements RejectedExecutionHandler {
public DiscardOldestPolicy() { }
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
e.getQueue().poll();
e.execute(r);
}
}
}
ThreadFactory
默认同一个 ThreadGroup 中一律使用 Executors.defaultThreadFactory() 创建线程,并且这些线程具有相同的 NORM_PRIORITY 优先级和非守护进程状态。通过提供不同的 ThreadFactory,可以改变线程的名称、线程组、优先级、守护进程状态等等。
private static class DefaultThreadFactory implements ThreadFactory {
private static final AtomicInteger poolNumber = new AtomicInteger(1);
private final ThreadGroup group;
private final AtomicInteger threadNumber = new AtomicInteger(1);
private final String namePrefix;
DefaultThreadFactory() {
SecurityManager s = System.getSecurityManager();
group = (s != null) ? s.getThreadGroup() :
Thread.currentThread().getThreadGroup();
namePrefix = "pool-" +
poolNumber.getAndIncrement() +
"-thread-";
}
public Thread newThread(Runnable r) {
Thread t = new Thread(group, r,
namePrefix + threadNumber.getAndIncrement(),
0);
if (t.isDaemon())
t.setDaemon(false);
if (t.getPriority() != Thread.NORM_PRIORITY)
t.setPriority(Thread.NORM_PRIORITY);
return t;
}
}
ExecutorService执行方法:
- execute(Runnable)
这个方法接收一个Runnable实例,并且异步的执行,无法知道结果 - submit(Runnable)
这个方法接收一个Runnable实例,并且异步的执行,返回一个Future对象,可以检查结果
Future future = executorService.submit(new MyRunnable);
//方法会阻塞,返回null表示执行成功
future.get();
- submit(Callable)
也会返回一个Future对象,但是除此之外,submit(Callable)接收的是一个Callable的实现,Callable接口中的call()方法有一个返回值,可以返回任务的执行结果
Future future = executorService.submit(new MyCallable());
//方法会阻塞,返回值为Call()
future.get();
当我们使用完成ExecutorService之后应该关闭它,否则它里面的线程会一直处于运行状态。
举个例子,如果的应用程序是通过main()方法启动的,在这个main()退出之后,如果应用程序中的ExecutorService没有关闭,这个应用将一直运行。之所以会出现这种情况,是因为ExecutorService中运行的线程会阻止JVM关闭。
调用shutdown()方法之后,ExecutorService不会立即关闭,但是它不再接收新的任务,直到当前所有线程执行完成才会关闭。
调用shutdownNow()方法。这个动作将跳过所有正在执行的任务和被提交还没有执行的任务。但是它并不对正在执行的任务做任何保证,有可能它们都会停止,也有可能执行完成。
ScheduledExecutorService
定时任务线程池
- schedule (Runnable task, long delay, TimeUnit timeunit)
指定延迟之后运行task。这个方法有个问题,就是没有办法获知task的执行结果。如果我们想获得task的执行结果,我们可以传入一个Callable的实例 - schedule (Callable task, long delay, TimeUnit timeunit)
这个方法与schedule (Runnable task)类似,也是在指定延迟之后运行task,不过它接收的是一个Callable实例,此方法会返回一个ScheduleFuture对象,通过ScheduleFuture我们可以取消一个未执行的task,也可以获得这个task的执行结果 - scheduleAtFixedRate (Runnable, long initialDelay, long period, TimeUnit timeunit)
周期性的调度task执行。task第一次执行的延迟根据initialDelay参数确定,以后每一次执行都间隔period时长。
如果task的执行时间大于定义的period,那么下一个线程将在当前线程完成之后再执行。整个调度保证不会出现一个以上任务同时执行 - scheduleWithFixedDelay (Runnable, long initialDelay, long period, TimeUnit timeunit)
与scheduleAtFixedRate类似,scheduleWithFixedDelay中,period指的当前任务的结束执行时间到下个任务的开始执行时间。