创建线程:
创建线程有3中方式:继承Thread类,实现runable接口 或者是利用Callable和FutureTask的方式。
JDK线程池:
先来解释一下jdk线程池中容易混淆的几个名词:
1.Executor:线程池接口 爷爷辈的,只有一个execute方式 接受Runnable参数 。
2.Executors:相当于一个工具类,用来创建线程池的工厂,常用的几个newFixedThreadPool 、newScheduleThreadPool等都是通过他来创建的。
3.ExecutorService :他是Executor的子接口,提供了管理线程周期的方法,可以说平常说的线程池就是指ExecutorService
创建JDK线程池:
方法一:Executors创建:创建线程池我们上面讲过,可以用Executors的去创建线程池,他有许多静态方法去创建不同类型的线程池,包括:newFixedThreadPool 、newScheduleThreadPool、newSingleThreadPool等,不过为了让开发者了解线程池的机制,合理的使用线程池,不建议使用Executors的工厂方法创建。
方法二:ThreadPoolExecutor创建:
new ThreadPoolExecutor(int corePoolSize, int maximumPoolSize,long keepAliveTime, TimeUnit unit,BlockingQueue<Runnable> workQueue,RejectedExecutionHandler handler)
ThreadPoolExecutor是ExecutorService实现类,我们通过构造方法的方式创建线程池 ,这里有几个参数也很好理解;
corePoolSize :核心线程,线程池中核心的线程,如果线程数小于核心线程,则可以继续创建线程
maximumPoolSize:最大线程数,比核心线程大的情况下,多出的线程数可以用来创建非核心线程,非核心线程是会被回收的,相当于临时工。
keepAliveTime:非核心线程空闲的空闲时间,超出就会被回收
TimeUnit :空闲时间的单位
workQueue:阻塞队列,实现线程池的阻塞队列选择,比如LinkedBlockQueue用来可以创建定长的数据库连接池。
RejectedExecutionHandler :用来指定线程池满了之后所需要做的操作
有时候
ThreadPoolExecutor的构造方法中还有一个ThreadFactory的参数 ,这个是一个线程创建的工厂方法,可以自己来实现。
线程池的使用场景:
很多人虽然了解线程池,却还是不是很清楚什么时候需要用线程池,其实线程池的使用很广泛,很多地方你都可以去用他,比如你需要执行大量任务,且耗时较长的,例如批量发送短信邮件,批量插入日志等,都可以利用线程池管理,避免不必要的创建线程和销毁线程的资源损耗。
Spring线程池:
TaskExecutor—Spring异步线程池的接口类,其实质是java.util.concurrent.Executor
官方有7个实现类:
1.simpleAsyncTaskExecutor:每次调用都会新建线程,不会重复利用,不属于真正意义上的线程池。支持限流操作,可以指定concurrencyLimit参数指定线程数量。
2.SynTaskExecutor:同步的线程,也不算真的线程池
3.CurrentTaskExecutor:适配类不推荐使用
4.simpleThreadPoolTaskExecutor:线程池同时被quartz和非quartz使用,才需要使用此类。
5.ThreadPoolTaskExecutor:最常用的,实质对java.util.concurrent.ThreadPoolExecutor的包装。
Spring线程池的使用:
1.可以通过自动注入
@Autowired
private ThreadPoolTaskExecutor poolTaskExecutor;
2.可以通过XML或者srpingboot装配的方式自定义线程池属性
配置属性大致也jdk的配置属性类似,包括核心线程数 最大线程数 空闲时间 拒绝策略等等
Springboot如何使用@Asyn加ThreadPoolTaskExecutor实现异步短信发送
启动类加@EnableAsyn
@ServletComponentScan
@SpringBootApplication
@EnableAsync // 开启@Async注解
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
在配置线程池,可以用springBoot默认属性或者用@Configuration自定义。
方法上架@Asyn注解 可以指定线程池
@Async()
public void sendEmail(String name){
//这里使用logger 方便查看执行的线程是什么
logger.info("异步线程启动 started."+name);
}```