超详细 Springboot 线程池用法一(自用)

目录

前言

(1)@EnableAsync 和 @Async 很关键

(2)Thread 和 Runnable 要谨慎

(3)数据类型,线程安全 要牢记

(4)@Configuration 和 @Bean 很方便

(5)ThreadPoolExecutor 和 ThreadPoolTaskExecutor 怎么选

(6)上才艺!


前言

        线程池,顾名思义,可以类比一个水池,而每一个线程,都好比水池的水。因此,水池多大,看系统硬件配置,此处不多赘述。

        当然,关于线程池大小的设定,也有其他开发者对此做出了建议:

线程池大小的设置

        针对这个问题,我们首先要确认的是我们的需求是计算密集型还是IO密集型。

        如果是计算密集型,比较理想的方案是:线程数 = CPU核数 + 1,也可以设置成CPU核数*2,一般设置CPU*2

        如果是IO密集型,线程数 = CPU核心数/(1-阻塞系数),这个组赛系数一般为0.8~0.9之间,也可以取0.8或者0.9.
————————————————
版权声明:本文为CSDN博主「one_smail」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_40386113/article/details/127581333

(1)@EnableAsync 和 @Async 很关键

@EnableAsync // 这注解允许异步

@Async // 这注解的函数会被异步处理

        线程池的作用,很大程度上是为了并发,高效处理任务。而异步处理任务,可以有效提高处理任务的吞吐量。

(2)Thread 和 Runnable 要谨慎

        Thread同样可以创建线程,但是线程使用完之后需要对线程资源进行销毁回收,这本身对资源的消耗不小,且容易造成线程上下文切换问题,甚至线程管理不当容易造成资源耗尽。因此需要使用线程时,要谨慎选择Thread。

(3)数据类型,线程安全 要牢记

        如果有多线程共享数据的方式,要牢记各种使用场景的线程安全数据类型。如:

  1.  AtomicInteger 原子int整型;
  2.  AtomicLong 原子long整型;
  3.  AtomicBoolean 原子boolean;
  4. List 这三种都是线程安全型:
    1. List<T> vector = new Vector<>();
    2. List<T> listSyn = Collections.synchronizedList(new ArrayList<>());
    3. List<T> copyList = new CopyOnWriteArrayList<>();

(4)@Configuration 和 @Bean 很方便

@Configuration 注解的配置类

@Bean 将实例对象提交给IoC容器

        这对组合的搭配,让我们可以将实例对象的管理忽略,将更多的心思放在业务开发上。

        值得点出来的还有 @Autowired(required = true) 自动装配实例对象;如果你不想自动装配,则 required = false。

(5)ThreadPoolExecutor 和 ThreadPoolTaskExecutor 怎么选

        首先这两种线程池方式,本质上一样,ThreadPoolTaskExecutor 源码上是在 ThreadPoolExecutor 上再加了一层包装,为了更方便在spring框架中使用。而这里只讲ThreadPoolTaskExecutor。

(6)上才艺!

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.ThreadPoolExecutor;

@EnableAsync
@Configuration
public class ThreadPoolCfg {
    // 获取服务器的cpu个数
    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
    // 核心线程数量
    private static final int COUR_SIZE = CPU_COUNT * 2;
    // 线程最大数量
    private static final int MAX_COUR_SIZE = COUR_SIZE * 4;

    // 提交给IoC容器,装配名称为 "threadPoolTaskExecutor"
    @Bean("threadPoolTaskExecutor")
    public ThreadPoolTaskExecutor taskExecutor(){
        ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
        // 核心线程数量
        threadPoolTaskExecutor.setCorePoolSize(COUR_SIZE);
        // 最大线程数
        threadPoolTaskExecutor.setMaxPoolSize(MAX_COUR_SIZE);
        // 线程缓冲任务队列
        threadPoolTaskExecutor.setQueueCapacity(MAX_COUR_SIZE * 2);
        // 线程空闲时间
        threadPoolTaskExecutor.setKeepAliveSeconds(60);
        // 线程名称前缀
        threadPoolTaskExecutor.setThreadNamePrefix("taskExecutor-");
        // 线程拒绝任务处理策略:没精力处理时,直接拒绝任务;若执行程序已被关闭,则直接丢弃
        threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        return threadPoolTaskExecutor;
    }
}
// 这是个测试
public void test() {
    for (int i = 0; i < 10; i++){
        taskExecutor.execute(this::do_test);
    }
     System.out.println("main thread:" + Thread.currentThread().getName());
}

@Async("threadPoolTaskExecutor")
public void do_test() {
    System.out.println("thread name:" + Thread.currentThread().getName());
}

 以下则是测试结果,可以很明显看到线程的不同。

猜你喜欢

转载自blog.csdn.net/qq_15855921/article/details/130078327