线程池的使用
为什么要用线程池
如果在使用线程的时候就去创建一个新线程, 当并发的线程数量很多, 并且每个线程都是执行一个时间很短的任务就结束了, 系统在创建和销毁线程上花费的时间和消耗的系统资源都相当大, 甚至要比处理任务的时间和资源要多的多, 同时活动的线程也需要消耗系统资源.
使用线程池的好处
- 降低资源消耗
- 提高效应速度
- 提高线程的可管理性
线程池架构
Executor是一个顶层接口, 它只声明了一个方法 execute(Runnable), 返回值 void, 字面上就是用来执行传进去的任务的
ExecutorService接口继承了Executor 接口, 并声明了一些方法 submit, invokeAll, invokeAny, shoutDown, shoutDownNow等
抽象类AbstractExecutorService实现了 ExecutorService 接口, 基本实现了 ExecutorService 中声明的所有方法
ThreadPoolExecutor继承了抽象类AbstractExecutorService
具体的介绍不多说, 在别的博客已经有很详细的介绍比如
http://www.cnblogs.com/dolphin0520/p/3932921.html 写的很好(有错误地方)
具体使用
Executors静态工厂虽然提供了几种创建常用线程池方法, 但是不建议慎用 Executors 去创建, 而是通过 ThreadPoolExecutor 的方式, 可以更加明确线程池的运行规则, 避免系统资源耗尽的风险
Executors 各个方法的弊端:
- newFixedThreadPool 和 newSingleThreadExecutor:
主要问题是堆积的请求处理队列可能会耗费非常大的内存- newCachedThreadPool 和 newScheduledThreadPool:
主要问题是线程数最大数是 Integer.MAX_VALUE, 可能会创建数量非常多的线程
如何创建线程池
方式一
// org.apache.commons.lang3.concurrent.BasicThreadFactory
new ScheduledThreadPoolExecutor(1,
new BasicThreadFactory.Builder().namingPattern("example-schedule-pool-%d").daemon(true).build());
方式二
ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("demo-pool-%d").build();
ThreadPoolExecutor pool =
new ThreadPoolExecutor(5, 200, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(1024),
namedThreadFactory, new ThreadPoolExecutor.AbortPolicy());
pool.execute(() -> {
System.out.println("当前线程: " + Thread.currentThread().getName());
pool.shutdown();
});
待更新…