java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > ThreadPoolTaskExecutor线程池

Spring中的ThreadPoolTaskExecutor线程池使用详解

作者:卷不动躺不平的粥

这篇文章主要介绍了Spring中的ThreadPoolTaskExecutor线程池使用详解,ThreadPoolTaskExecutor 是 Spring框架提供的一个线程池实现,用于管理和执行多线程任务,它是TaskExecutor接口的实现,提供了在 Spring 应用程序中创建和配置线程池的便捷方式,需要的朋友可以参考下

一、配置

1.1 将 ThreadPoolTaskExecutor 注入到 spring 容器内

@Configuration
public class ThreadTaskPoolExecutorConfiguration {
    @Bean
    public ThreadPoolTaskExecutor threadPoolTaskExecutor(){
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        // 核心线程数
        taskExecutor.setCorePoolSize(5);
        // 最大线程数
        taskExecutor.setMaxPoolSize(15);
        // 队列大小 默认使用LinkedBlockingQueue
        taskExecutor.setQueueCapacity(100);
        // 线程最大空闲时间
        taskExecutor.setKeepAliveSeconds(300);
        // 拒绝策略 默认new ThreadPoolExecutor.AbortPolicy()
        taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // 线程名称前缀
        taskExecutor.setThreadNamePrefix("My-Task-Executor-");
        //交给spring托管的会自动初始化,因为实现了InitializingBean接口
        // taskExecutor.initialize();
        return taskExecutor;
    }
}

1.2 拒绝策略配置

rejectedExecutionHandler 字段用于配置拒绝策略,常用的拒绝策略如下:

其他说明:

1.3 配置线程池个数

二、处理流程

  1. 当一个任务被提交到线程池时,首先查看线程池的核心线程是否都在执行任务,否就选择一条线程执行任务,是就执行第二步。
  2. 查看核心线程池是否已满,不满就创建一条线程执行任务,否则执行第三步。
  3. 查看任务队列是否已满,不满就将任务存储在任务队列中,否则执行第四步。
  4. 查看线程池是否已满,不满就创建一条线程执行任务,否则就按照策略处理无法执行的任务。

在 ThreadPoolExecutor 中表现为:

三、关闭线程池

调用shutdown或者shutdownNow,两者都不会接受新的任务,而且通过调用要停止线程的interrupt方法来中断线程,有可能线程永远不会被中断,不同之处在于shutdownNow会首先将线程池的状态设置为STOP,然后尝试停止所有线程(有可能导致部分任务没有执行完)然后返回未执行任务的列表。而shutdown则只是将线程池的状态设置为shutdown,然后中断所有没有执行任务的线程,并将剩余的任务执行完。

四、监控线程池状态

常用状态:

通过继承线程池,重写beforeExecute,afterExecute 和 terminated 方法来在线程执行任务前,线程执行任务结束,和线程终结前获取线程的运行情况,根据具体情况调整线程池的线程数量。

五、实战

@RunWith(SpringRunner.class)
@SpringBootTest(classes = TestApplication.class)
public class TestApplicationTests {
    // 注入ThreadPoolTaskExecutor
    @Resource
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;
    @Test
    public void ThreadTest(){
        System.out.println(threadPoolTaskExecutor);
        System.out.println("new Runnable()");
        // 创建并执行线程,方式一
        threadPoolTaskExecutor.execute(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 100; i++) {
                    System.out.println("new Runnable()"+i+"当前线程"+Thread.currentThread().getName());
                }
            }
        });
        // // 创建并执行线程,方式二
        System.out.println("lambda");
        threadPoolTaskExecutor.execute(() -> {
            for (int i = 0; i < 100; i++) {
                System.out.println("lambda"+i+"当前线程"+Thread.currentThread().getName());
            }
        });
    }
}

运行截图:

用lambda表达式实现Runnable

我开始使用Java 8时,首先做的就是使用lambda表达式替换匿名类,而实现Runnable接口是匿名类的最好示例。

看一下Java 8之前的runnable实现方法,需要4行代码,而使用lambda表达式只需要一行代码。我们在这里做了什么呢?那就是用() -> {}代码块替代了整个匿名类。

// Java 8之前:
new Thread(new Runnable() {
 @Override
 public void run() {
 System.out.println("Before Java8, too much code for too little to do");
 }
}).start();
//Java 8方式:
new Thread( () -> System.out.println("In Java8, Lambda expression rocks !!") ).start();

到此这篇关于Spring中的ThreadPoolTaskExecutor线程池使用详解的文章就介绍到这了,更多相关ThreadPoolTaskExecutor线程池内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文