文章目录
ThreadPoolExecutor
这个类是JDK中的线程池类,继承自Executor
1、newCachedThreadPool
创建一个线程池,如果线程池中的线程数量过大,它可以有效的回收多余的线程,如果线程数不足,那么它可以创建新的线程。
public class CacheThreadPoolTest {
private static int counter = 0;
public static void main(String[] args) throws Exception {
ThreadPoolExecutor threadPool = (ThreadPoolExecutor) Executors.newCachedThreadPool();
//提交100个任务
for(int i = 0; i < 1000; i++) {
//submit()会异常处理 底层-> excute(new Runnable(){})
threadPool.execute(new Add());
// threadPool.submit(new Add());
}
threadPool.shutdown();
//打印最多使用线程数
System.out.println("核心线程数: " +threadPool.getCorePoolSize());
System.out.println("Largest线程数: " +threadPool.getLargestPoolSize());
System.out.println("同时执行的Maximum线程数: " +threadPool.getMaximumPoolSize());
System.out.println(counter);
}
static class Add implements Runnable {
@Override
public void run() {
counter++;
}
}
}
2、newFixedThreadPool
这种方式可以指定线程池中的线程数。举个栗子,如果一间澡堂子最大只能容纳20个人同时洗澡,那么后面来的人只能在外面排队等待。
public class FixedThreadPoolTest {
private static int counter = 0;
public static void main(String[] args) throws Exception {
ThreadPoolExecutor threadPool = (ThreadPoolExecutor) Executors.newFixedThreadPool(10);
//提交1000个任务
for(int i = 0; i < 1000; i++) {
//submit()会异常处理 底层-> excute(new Runnable(){})
threadPool.submit(new Add());
}
threadPool.shutdown();
//打印最多使用线程数
System.out.println("核心线程数: " +threadPool.getCorePoolSize());
System.out.println("Largest线程数: " +threadPool.getLargestPoolSize());
System.out.println("队列: " +threadPool.getQueue());
System.out.println("同时执行的Maximum线程数: " +threadPool.getMaximumPoolSize());
System.out.println(counter);
}
static class Add implements Runnable {
@Override
public void run() {
counter++;
}
}
}
3、newScheduledThreadPool
该线程池支持定时,以及周期性的任务执行,我们可以延迟任务的执行时间,也可以设置一个周期性的时间让任务重复执行。
定时任务默认是单线程执行,在实际应用场景中可以通过配置 定时任务线程池,实现定时任务并发执行
public class ScheduledThreadPoolTest {
private static int counter = 0;
public static void main(String[] args) throws Exception {
ThreadPoolExecutor threadPool = (ThreadPoolExecutor) Executors.newScheduledThreadPool(10);
//提交1000个任务
for(int i = 0; i < 1000; i++) {
//submit()会异常处理 底层-> excute(new Runnable(){})
threadPool.submit(new Add());
}
threadPool.shutdown();
//打印最多使用线程数
System.out.println("核心线程数: " +threadPool.getCorePoolSize());
System.out.println("Largest线程数: " +threadPool.getLargestPoolSize());
System.out.println("同时执行的Maximum线程数: " +threadPool.getMaximumPoolSize());
System.out.println(counter);
}
static class Add implements Runnable {
@Override
public void run() {
counter++;
}
}
}
4、newSingleThreadExecutor
这是一个单线程池,至始至终都由一个线程来执行。
public class SingleThreadPoolTest {
private static int counter = 0;
public static void main(String[] args) throws Exception {
ExecutorService threadPool = Executors.newSingleThreadExecutor();
//提交1000个任务
for(int i = 0; i < 1000; i++) {
//submit()会异常处理 底层-> excute(new Runnable(){})
threadPool.submit(new Add());
}
threadPool.shutdown();
//打印最多使用线程数
System.out.println(counter);
}
static class Add implements Runnable {
@Override
public void run() {
counter++;
}
}
ThreadPoolTaskExecutor
这个类则是spring包下的,是sring为我们提供的线程池类
通过配置类的方式配置线程池,然后注入。(或者spring的配置文件)
1创建线程池
@EnableAsync
@Configuration
public class ExecturConfig {
@Bean("taskExector")
public Executor taskExector() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
int i = Runtime.getRuntime().availableProcessors();//获取到服务器的cpu内核
executor.setCorePoolSize(10);//核心池大小
//executor.setMaxPoolSize(100);//最大线程数
//executor.setQueueCapacity(1000);//队列程度
//executor.setKeepAliveSeconds(1000);//线程空闲时间
//executor.setThreadNamePrefix("tsak-asyn");//线程前缀名称
//executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());//配置拒绝策略
return executor;
然后通过自动注入的方式注入线程池
2编写多线程方法
@Resource(name=“taskExecutor”)
ThreadPoolTaskExecutor taskExecutor;
// 或者可以直接@Autowried
@AutoWired
ThreadPoolTaskExecutor taskExecutor
@Component
public class ServerStarter{
@Async("taskExector")
public void startServer(){
//业务逻辑
}
}
3编写测试调用多线程方法
//测试
public static void main(String[] args) {
new ServerStarter().startServer();
}
}
构造函数中调用,目的就是在类的初始化的时候进行调用。
//实际开发
@Component
public class Server {
public Server(ServerStarter starter) {
starter.startServer();
}
}
手写线程池的几种方式
ThreadPoolTaskExecutor和ThreadPoolExecutor区别
分析下继承关系:
1、ThreadPoolTaskExecutor extends (2)ExecutorConfigurationSupport
implements (3)AsyncListenableTaskExecutor, (4)SchedulingTaskExecutor
2、 ExecutorConfigurationSupport extends CustomizableThreadFactory implements BeanNameAware, InitializingBean, DisposableBean
3、public interface AsyncListenableTaskExecutor extends AsyncTaskExecutor
4、public interface SchedulingTaskExecutor extends AsyncTaskExecutor
从上继承关系可知:
ThreadPoolExecutor是一个java类不提供spring生命周期和参数装配。
ThreadPoolTaskExecutor实现了InitializingBean, DisposableBean ,xxaware等,具有spring特性
AsyncListenableTaskExecutor提供了监听任务方法(相当于添加一个任务监听,提交任务完成都会回调该方法)
简单理解:
1、ThreadPoolTaskExecutor使用ThreadPoolExecutor并增强,扩展了更多特性
2、ThreadPoolTaskExecutor只关注自己增强的部分,任务执行还是ThreadPoolExecutor处理。
3、前者spring自己用着爽,后者离开spring我们用ThreadPoolExecutor爽。
注意:ThreadPoolTaskExecutor 不会自动创建ThreadPoolExecutor需要手动调initialize才会创建
如果@Bean 就不需手动,会自动InitializingBean的afterPropertiesSet来调initialize