线程池就是一个可以复用线程的技术。
不使用线程池的问题 :如果用户每发起一个请求,后台就创建一个新线程来处理,下次新任务来了又要创建新线程,而创建新线程的开销是很大的,这样会严重影响系统的性能。

方式一:使用ExecutorService的实现类ThreadPoolExecutor自创建一个线程池对象。
方式二:使用Executors(线程池的工具类)调用方法返回不同特点的线程池对象。
- public ThreadPoolExecutor(int corePoolSize,
- int maximumPoolSize,
- long keepAliveTime,
- TimeUnit unit,
- BlockingQueue
workQueue, - ThreadFactory threadFactory,
- RejectedExecutionHandler handler)
线程池常见面试题:临时线程什么时候创建啊?
新任务提交时发现核心线程都在忙,任务队列也满了,并且还可以创建临时线程,此时才会创建临时线程。
什么时候会开始拒绝任务?
核心线程和临时线程都在忙,任务队列也满了,新的任务过来的时候才会开始任务拒绝。
- ExecutorService pools = new ThreadPoolExecutor(3, 5
- , 8 , TimeUnit.SECONDS, new ArrayBlockingQueue<>(6),
- Executors.defaultThreadFactory() , new ThreadPoolExecutor.AbortPolicy());
新任务拒绝策略
- public class MyRunnable implements Runnable{
- @Override
- public void run() {
- for (int i = 0; i < 5; i++) {
- System.out.println(Thread.currentThread().getName() + "输出了:HelloWorld ==> " + i);
- }
- try {
- System.out.println(Thread.currentThread().getName() + "本任务与线程绑定了,线程进入休眠了~~~");
- Thread.sleep(10000000);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
- public class ThreadPoolDemo1 {
- public static void main(String[] args) {
- // 1、创建线程池对象
- /**
- public ThreadPoolExecutor(int corePoolSize,
- int maximumPoolSize,
- long keepAliveTime,
- TimeUnit unit,
- BlockingQueue
workQueue, - ThreadFactory threadFactory,
- RejectedExecutionHandler handler)
- */
- ExecutorService pool = new ThreadPoolExecutor(3, 5 ,
- 6, TimeUnit.SECONDS, new ArrayBlockingQueue<>(5) , Executors.defaultThreadFactory(),
- new ThreadPoolExecutor.AbortPolicy() );
-
- // 2、给任务线程池处理。
- Runnable target = new MyRunnable();
- pool.execute(target);
- pool.execute(target);
- pool.execute(target);
-
- pool.execute(target);
- pool.execute(target);
- pool.execute(target);
- pool.execute(target);
- pool.execute(target);
-
- // 创建临时线程
- pool.execute(target);
- pool.execute(target);
- // // 不创建,拒绝策略被触发!!!
- // pool.execute(target);
-
- // 关闭线程池(开发中一般不会使用)。
- // pool.shutdownNow(); // 立即关闭,即使任务没有完成,会丢失任务的!
- pool.shutdown(); // 会等待全部任务执行完毕之后再关闭(建议使用的)
- }
- }
- /**
- 1、定义一个任务类 实现Callable接口 应该申明线程任务执行完毕后的结果的数据类型
- */
- public class MyCallable implements Callable
{ - private int n;
- public MyCallable(int n) {
- this.n = n;
- }
-
- /**
- 2、重写call方法(任务方法)
- */
- @Override
- public String call() throws Exception {
- int sum = 0;
- for (int i = 1; i <= n ; i++) {
- sum += i;
- }
- return Thread.currentThread().getName()
- + "执行 1-" + n+ "的和,结果是:" + sum;
- }
- }
- public class ThreadPoolDemo2 {
- public static void main(String[] args) throws Exception {
- // 1、创建线程池对象
- /**
- public ThreadPoolExecutor(int corePoolSize,
- int maximumPoolSize,
- long keepAliveTime,
- TimeUnit unit,
- BlockingQueue
workQueue, - ThreadFactory threadFactory,
- RejectedExecutionHandler handler)
- */
- ExecutorService pool = new ThreadPoolExecutor(3, 5 ,
- 6, TimeUnit.SECONDS, new ArrayBlockingQueue<>(5) , Executors.defaultThreadFactory(),
- new ThreadPoolExecutor.AbortPolicy() );
-
- // 2、给任务线程池处理。
- Future
f1 = pool.submit(new MyCallable(100)); - Future
f2 = pool.submit(new MyCallable(200)); - Future
f3 = pool.submit(new MyCallable(300)); - Future
f4 = pool.submit(new MyCallable(400)); - Future
f5 = pool.submit(new MyCallable(500)); -
- // String rs = f1.get();
- // System.out.println(rs);
-
- System.out.println(f1.get());
- System.out.println(f2.get());
- System.out.println(f3.get());
- System.out.println(f4.get());
- System.out.println(f5.get());
- }
- }
Executors:线程池的工具类通过调用方法返回不同类型的线程池对象。

注意:Executors的底层其实也是基于线程池的实现类ThreadPoolExecutor创建线程池对象的。
大型并发系统环境中使用Executors如果不注意可能会出现系统风险。
