线程池概述
线程池就是一个可以复用线程的技术。
不使用线程池的问题 :如果用户每发起一个请求,后台就创建一个新线程来处理,下次新任务来了又要创建新线程,而创建新线程的开销是很大的,这样会严重影响系统的性能。
线程池实现的API、参数说明
JDK 5.0起提供了代表线程池的接口:ExecutorService。
如何得到线程池对象:
方式一:使用ExecutorService的实现类ThreadPoolExecutor自创建一个线程池对象。
方式二:使用Executors(线程池的工具类)调用方法返回不同特点的线程池对象。
ThreadPoolExecutor构造器的参数说明:
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler)
线程池常见面试题:
临时线程什么时候创建啊?
新任务提交时发现核心线程都在忙,任务队列也满了,并且还可以创建临时线程,此时才会创建临时线程。
什么时候会开始拒绝任务?
核心线程和临时线程都在忙,任务队列也满了,新的任务过来的时候才会开始任务拒绝。
ThreadPoolExecutor创建线程池对象示例
ExecutorService pools = new ThreadPoolExecutor(3, 5, 8 , TimeUnit.SECONDS, new ArrayBlockingQueue<>(6),Executors.defaultThreadFactory() , new ThreadPoolExecutor.AbortPolicy());
ExecutorService的常用方法
新任务拒绝策略
线程池处理Runnable任务
public class MyRunnable implements Runnable{@Overridepublic 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<Runnable> 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(); // 会等待全部任务执行完毕之后再关闭(建议使用的)}
}
线程池处理Callable任务
/**1、定义一个任务类 实现Callable接口 应该申明线程任务执行完毕后的结果的数据类型*/
public class MyCallable implements Callable<String>{private int n;public MyCallable(int n) {this.n = n;}/**2、重写call方法(任务方法)*/@Overridepublic 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<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler)*/ExecutorService pool = new ThreadPoolExecutor(3, 5 ,6, TimeUnit.SECONDS, new ArrayBlockingQueue<>(5) , Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy() );// 2、给任务线程池处理。Future<String> f1 = pool.submit(new MyCallable(100));Future<String> f2 = pool.submit(new MyCallable(200));Future<String> f3 = pool.submit(new MyCallable(300));Future<String> f4 = pool.submit(new MyCallable(400));Future<String> 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:线程池的工具类通过调用方法返回不同类型的线程池对象。
api
注意:Executors的底层其实也是基于线程池的实现类ThreadPoolExecutor创建线程池对象的。
Executors使用可能存在的陷阱
大型并发系统环境中使用Executors如果不注意可能会出现系统风险。