为什么使用线程池?
- 背景:经常创建和销毁,使用量特别大的资源,比如并发情况下的线程,对性能影响很大
- 思路:提前创建好多个线程,放入线程池中,使用时直接获取,使用完放回池中,可以避免频繁创建销毁,实现重复利用,类似于生活中的单车
- 好处:
- 提高响应速度(减少了创建新线程的时间)
- 降低资源消耗(重复利用线程池中的线程,不需要每次都创建)
- 便于线程管理
- corePoolSize:核心池的大小
- maxmumPoolSize:最大线程数
- keepAliveTime:线程没有任务时最多保持多长时间后终止
如何使用线程池
JDK5.0起提供了线程池相关API:ExecutorService和Executor
- ExecutorService:真正的线程池接口:常见子类ThreadPoolExecutor
- Void execute(Runnable command):执行任务/命令,没有返回值,一般用来执行Runnable
- <T>Future<T> submit(Callable<T>task):执行任务,有返回值,一般又来执行Callable
- Void shutdown():关闭线程池
- Executor:工具类,线程池的工厂类,用于创建并返回不同类型的线程池
ExecutorService 也属于JUC(并发)下的
//newFixedThreadPool参数为线程池大小
ExecutorService executorService= Executors.newFixedThreadPool(10);
一般线程池使用步骤
- 创建服务,创建线程池 newFixedThreadPool(10);
- 建完线程池把线程丢进去 执行runnable接口的实现类 execute(new ThreadPool());
- 关闭连接 shutdown();
package com.wyh.thread; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * @program: Thread * @description: 测试线程池 * @author: 魏一鹤 * @createDate: 2022-01-22 21:08 **/ public class TestThreadPool { public static void main(String[] args){ //1 创建服务,创建线程池 //newFixedThreadPool参数为线程池大小 ExecutorService executorService= Executors.newFixedThreadPool(10); //2 创建完线程池把线程丢进去 执行runnable接口的实现类 executorService.execute(new ThreadPool()); executorService.execute(new ThreadPool()); executorService.execute(new ThreadPool()); executorService.execute(new ThreadPool()); executorService.execute(new ThreadPool()); //3 关闭连接 executorService.shutdown(); } } class ThreadPool implements Runnable{ @Override public void run() { System.out.println(Thread.currentThread().getName()); } }
Java通过Executors提供三种线程池,分别为:
- newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
- newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
- newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
线程池核心参数
- corePoolSize(核心线程数)
(1)核心线程会一直存在,即使没有任务执行;
(2)当线程数小于核心线程数的时候,即使有空闲线程,也会一直创建线程直到达到核心线数;
(3)设置allowCoreThreadTimeout=true(默认false)时,核心线程会超时关闭。
- queueCapacity(任务队列容量)
也叫阻塞队列,当核心线程都在运行,此时再有任务进来,会进入任务队列,排队等待线程执行。
- maxPoolSize(最大线程数)
(1)线程池里允许存在的最大线程数量;
(2)当任务队列已满,且线程数量大于等于核心线程数时,会创建新的线程执行任务;
(3)线程池里允许存在的最大线程数量。当任务队列已满,且线程数量大于等于核心线程数时,会创建新的线程执行任务。
- keepAliveTime(线程空闲时间)
(1)当线程空闲时间达到keepAliveTime时,线程会退出(关闭),直到线程数等于核心线程数;
(2)如果设置了allowCoreThreadTimeout=true,则线程会退出直到线程数等于零
- allowCoreThreadTimeout(允许核心线程超时)
- rejectedExecutionHandler(任务拒绝处理器)
(1)当线程数量达到最大线程数,且任务队列已满时,会拒绝任务;
(2)调用线程池shutdown()方法后,会等待执行完线程池的任务之后,再shutdown()。如果在调用了shutdown()方法和线程池真正shutdown()之间提交任务,会拒绝新任务。
线程池参数默认值
corePoolSize = 1
queueCapacity = Integer.MAX_VALUE
maxPoolSize = Integer.MAX_VALUE
keepAliveTime = 60秒
allowCoreThreadTimeout = false
rejectedExecutionHandler = AbortPolicy()