此时就需要ExecutorService登场了,它是Executor的一个子接口,对其进行了扩展,方法如下:
public interface ExecutorService extends Executor { void shutdown(); // 优雅地关闭,这个关闭会持续一段时间,以等待已经提交的任务去执行完成(但是在shutdown之后提交的任务会被拒绝) List<Runnable> shutdownNow(); // 粗暴地关闭,这个关闭会立即关闭所有正在执行的任务,并返回工作队列中等待的任务 boolean isShutdown(); boolean isTerminated(); // 用来等待线程的执行 // 如果在timeout之内,线程都执行完了,则返回true; // 如果等了timeout,还没执行完,则返回false; // 如果timeout之内,线程被中断,则抛出中断异常 boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException; <T> Future<T> submit(Callable<T> task); <T> Future<T> submit(Runnable task, T result); }从上面可以看到,线程池的生命周期分三步:
运行:创建后就开始运行
关闭:调用shutdown进入关闭状态
已终止:所有线程执行完毕
总结线程池的底层类 ThreadPoolExecutor:核心概念就是核心线程数、最大线程数、工作队列、拒绝策略
为啥阿里不建议使用 Executors来创建线程池?:因为会导致OOM,解决办法就是自定义ThreadPoolExecutor,为最大线程数和工作队列设置边界
线程池的生命周期ExecutorService:运行状态(创建后进入)、关闭状态(shutdown后进入)、已终止状态(所有线程都执行完成后进入)
参考内容:
《Java并发编程实战》
《实战Java高并发》
newFixedThreadPool的弊端:https://my.oschina.net/langwanghuangshifu/blog/3208320
银行办业务的场景参考:https://b23.tv/ygGjTH
后记愿你的意中人亦是中意你之人