目录
什么是线程池?
线程池就是一个可以复用线程的技术。
不使用线程池的问题
谁代表线程池?
如何得到线程池对象
方式一:使用ExecutorService的实现类ThreadPoolExecutor自创建一个线程池对象
方式二:使用Executors(线程池的工具类)调用方法返回不同特点的线程池对象
ThreadPoolExecutor构造器的参数说明
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
参数一:指定线程池的线程数量(核心线程): corePoolSize --------------------不能小于0
参数二:指定线程池可支持的最大线程数: maximumPoolSize ------------------最大数量 >= 核心线程数量
参数三:指定临时线程的最大存活时间: keepAliveTime --------------------------不能小于0
参数四:指定存活时间的单位(秒、分、时、天): unit -----------------------------时间单位
参数五:指定任务队列: workQueue ------------------------------------------不能为null
参数六:指定用哪个线程工厂创建线程:threadFactory ----------------------------不能为null
参数七:指定线程忙,任务满的时候,新任务来了怎么办: handler --------------------不能为null
ThreadPoolExecutor创建线程池对象示例
ExecutorService pools = new ThreadPoolExecutor(3, 5, 8 , TimeUnit.SECONDS,
new ArrayBlockingQueue<>(6),Executors.defaultThreadFactory() ,
new ThreadPoolExecutor.AbortPolicy());
(此示例中常用线程有3个,一共可以同时执行5个线程(2个临时线程),当3个常用线程被占用,且任务队列中6个任务都占满了,则线程工厂会创建临时进程处理任务,当2个临时线程也被占用,再来任务的话就会被拒绝且抛出异常)
线程池常见面试题
临时线程什么时候创建啊?
新任务提交时发现核心线程都在忙,任务队列也满了,并且还可以创建临时线程,此时才会创建临时线程。
什么时候会开始拒绝任务?
核心线程和临时线程都在忙,任务队列也满了,新的任务过来的时候才会开始任务拒绝。
线程池如何处理Runnable任务
使用ExecutorService的方法:
void execute(Runnable target)
MyRunnable
- public class MyRunable implements Runnable{
-
- @Override
- public void run() {
- for (int i = 0; i < 5; i++) {
- System.out.println(Thread.currentThread().getName() + ":" + i);
- }
- System.out.println(Thread.currentThread().getName() + "进入休眠");
- try {
- Thread.sleep(1000000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
ThreadPool
- public static void main(String[] args) {
-
- //1、创建线程池对象
- ExecutorService pool = new ThreadPoolExecutor(3, 5, 6,
- TimeUnit.SECONDS, new ArrayBlockingQueue<>(5), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
-
- //2、任务给线程池处理
- Runnable target = new MyRunable();
- 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任务,并得到任务执行完后返回的结果。
使用ExecutorService的方法:
Futuresubmit(Callable command)
MyCallable
- public class MyCallable implements Callable<String>{
-
- private int n;
-
- public MyCallable(int n) {
-
- this.n = n;
- }
-
- //重写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;
- }
- }
ThreadPool
- public static void main(String[] args) throws Exception {
-
- //1、创建线程池对象
- ExecutorService pool = new ThreadPoolExecutor(3, 5, 6,
- TimeUnit.SECONDS, new ArrayBlockingQueue<>(5), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
-
- //2、任务给线程池处理
- // Callable target = new MyCallable(100);
- // Future<String> f1 = pool.submit(target);
- 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));
-
- // String s1 = f1.get();
- // System.out.println(s1);
- System.out.println(f1.get());
- System.out.println(f2.get());
- System.out.println(f3.get());
- System.out.println(f4.get());
- }
- }