线程池ExecutorService
线程池的使用方式,new 一个线程代码如下:
ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 2, 3, TimeUnit.MINUTES, new ArrayBlockingQueue<>(1),
(r) -> {
return new Thread(r, "name");
}, new ThreadPoolExecutor.AbortPolicy());
线程的工作方式
当线程池启动时刚开始没有线程,当有新的任务进来时会创建一个新的线程来执行任务,当不断有新的任务进来时会放到队列中去,前提是有界队列。当队列满了会创建( maximumPoolSize - corePoolSize)个空闲线程来执行,当任务数仍然达到 maximumPoolSize的最大值时,这时候就会执行拒绝策略。
工厂方法
public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(), threadFactory);
}
上面展示的是一个 核心线程数==最大线程数(没有紧急线程被创建的),因此也没有超时时间,此时是一个无界阻塞队列,会不断创建线程,这种方式适合已知的线程数和等待时间比较长的。
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L,
TimeUnit.SECONDS, new SynchronousQueue<Runnable>());
}
核心线程数是0,最大线程数是 Integer.MAX_VALUE,全部都是空闲线程60s后回收,一个可根据需要创建新线程的线程池,如果现有线程没有可用的则新建一个线程,如果有空闲线程则复用该线程。并且终止线程池中已经使用超过60s的线程,因此长时间未使用的不会使用任何资源。这种线程池比较灵活,对于短期异步的线程池可用。
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
对于多个任务排队执行,线程固定为1,任务多于1会放入无界队列,任务执行完毕这唯一的线程也不会释放。与只创建一个线程执行任务对比这样可以保证线程执行失败后可以有新的补救措施,线程池会创建一个新的线程保证池的工作。
提交任务
//提交任务
Future<?> submit(Runnable task);
//提交一个有返回值的任务
<T> Future<T> submit(Runnable task, T result);
//提交全部任务
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
long timeout, TimeUnit unit)
throws InterruptedException;
shutdown
线程池变成SHUTDOWN状态
不再接受新的线程
会执行完正在执行的线程(包括队列中)
不会阻塞线程的执行
void shutdown();
线程池变成STOP状态
不会接受新的任务
会将任务中的队列返回
并用interrupt 的方式中断正在执行的任务
List 会将队列返回
List<Runnable> shutdownNow();
调用shutdown() 方法后,调用线程不会等待所有的线程结束,可以利用此方法等待
boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException;