首页 > 编程语言 >Java线程池

Java线程池

时间:2024-09-01 23:24:50浏览次数:6  
标签:状态 Java 创建 任务 线程 taskExecutor import

文章目录


为什么要使用线程池

  • 在实际的项目中,使用多线程时严禁直接new线程,必须要结合线程池来维护和创建线程。
  • 因为频繁的开启线程或者停止线程,线程需要重新被 cpu 从就绪到运行状态调度,需要发生 cpu 的上下文切换,效率非常低。
  • 线程池的好处是减少在创建和销毁线程上所消耗的时间以及系统资源的开销,解决资源不足的问题。
  • 如果不使用线程池,有可能造成系统创建大量同类线程而导致消耗完内存或者“过度切换”的问题。

线程池有哪些作用?

线程池的作用在于统一维护管理我们项目中的线程。 核心点就是复用机制

  1. 降低资源消耗:通过池化技术重复利用已创建的线程,降低线程创建和销毁造成的损耗。
  2. 提高响应速度:任务到达时,无需等待线程创建即可立即执行。
  3. 提高线程的可管理性:线程是稀缺资源,如果无限制创建,不仅会消耗系统资源,还会因为线程的不合理分布导致资源调度失衡,降低系统的稳定性。使用线程池可以进行统一的分配、调优和监控。
  4. 提供更多更强大就允许任务延期执行或定期执行。

线程池的创建方式

Executors.newCachedThreadPool(); 可缓存线程池
Executors.newFixedThreadPool();可定长度 限制最大线程数
Executors.newScheduledThreadPool() ; 可定时
Executors.newSingleThreadExecutor(); 单例
上面的创建方式底层采用的是无界的LinkedBlockingQueue队列,可能会有内存溢出的的问题。
真实开发中底层都是基于 ThreadPoolExecutor 构造函数封装使用线程池。

Executors.newFixedThreadPool()使用的ThreadPoolExecutor参数

    public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }

ThreadPoolExecutor核心参数

  • corePoolSize:核心线程数量(一直正在保持运行的线程)
  • maximumPoolSize:最大线程数(线程池允许创建的最大线程数)。满足最大线程数>=核心线程数
    如当核心线程数量是为2(一直在运行状态),最大线程数是4(是当我们队列容量满了 就触发创建线程)
  • keepAliveTime:超出corePoolSize后创建的线程(最大线程数)的存活时间。
  • unit:keepAliveTime的时间单位。
  • workQueue:任务队列,用于保存待执行的任务。
    详情可以看这篇文章:阻塞队列BlockingQueue
  • threadFactory:线程池内部创建线程所用的工厂。
  • handler:任务无法执行时的处理器。

线程池的运行流程

  1. 当线程数小于核心线程数时,创建线程。
  2. 当线程数大于等于核心线程数,且任务队列未满时,将任务放入任务队列。
  3. 当线程数大于等于核心线程数,且任务队列已满
    1.若线程数小于最大线程数,创建线程
    2.若线程数等于最大线程数,抛出异常,拒绝任务

线程池内部的五种状态

  1. RUNNING
    状态说明:线程池处在RUNNING状态时,能够接收新任务,以及对已添加的任务进行处理。
    状态切换:线程池的初始化状态是RUNNING。换句话说,线程池被一旦被创建,就处于RUNNING状态,并且线程池中的任务数为0!
  2. SHUTDOWN
    状态说明:线程池处在SHUTDOWN状态时,不接收新任务,但能处理已添加的任务。
    状态切换:调用线程池的shutdown()接口时,线程池由RUNNING -> SHUTDOWN。
  3. STOP
    状态说明:线程池处在STOP状态时,不接收新任务,不处理已添加的任务,并且会中断正在处理的任务。
    状态切换:调用线程池的shutdownNow()接口时,线程池由(RUNNING or SHUTDOWN ) -> STOP。
  4. TIDYING
    状态说明:当所有的任务已终止,ctl记录的”任务数量”为0,线程池会变为TIDYING状态。当线程池变为TIDYING状态时,会执行钩子函数terminated()。terminated()在ThreadPoolExecutor类中是空的,若用户想在线程池变为TIDYING时,进行相应的处理;可以通过重载terminated()函数来实现。
    状态切换:当线程池在SHUTDOWN状态下,阻塞队列为空并且线程池中执行的任务也为空时,就会由 SHUTDOWN -> TIDYING。
    当线程池在STOP状态下,线程池中执行的任务为空时,就会由STOP -> TIDYING。
  5. TERMINATED
    状态说明:线程池彻底终止,就变成TERMINATED状态。
    状态切换:线程池处在TIDYING状态时,执行完terminated()之后,就会由 TIDYING -> TERMINATED。

实战使用

通常会创建一个配置类进行线程池参数配置,也可以将线程池封装为一个工具类,使用时调用。

代码示例:

import com.lc.soft.config.info.TimerThreadPoolConfig;
import org.springframework.beans.factory.annotation.Autowired;
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.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @author qf
 * @since 2024/08/31
 */
@Configuration
@EnableAsync
public class ThreadPoolConfig {

    @Autowired
    private TimerThreadPoolConfig timerThreadPoolConfig;

    /**
     * 定时器线程池
     *
     * @return
     */
    @Bean(name = "timerExecutor")
    public ThreadPoolTaskExecutor timerThreadPoolExecutor() {
        return getAsyncTaskExecutor("Timer-Executor-", timerThreadPoolConfig.getCoreSize(),
                timerThreadPoolConfig.getMaxSize(), timerThreadPoolConfig.getQueueCapacity(),
                timerThreadPoolConfig.getKeepAliveSeconds(), null);
    }

   ...
   //不同业务建议配置不同的线程池

    /**
     * 统一异步线程池
     * @param threadNamePrefix
     * @param corePoolSize
     * @param maxPoolSize
     * @param queueCapacity
     * @param keepAliveSeconds
     * @param rejectedExecutionHandler 拒接策略 没有填null
     * @return
     */
    private ThreadPoolTaskExecutor getAsyncTaskExecutor(String threadNamePrefix, int corePoolSize, int maxPoolSize, int queueCapacity, int keepAliveSeconds, RejectedExecutionHandler rejectedExecutionHandler) {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        taskExecutor.setCorePoolSize(corePoolSize);
        taskExecutor.setMaxPoolSize(maxPoolSize);
        taskExecutor.setQueueCapacity(queueCapacity);
        taskExecutor.setThreadPriority(Thread.MAX_PRIORITY);//线程优先级
        taskExecutor.setDaemon(false);//是否为守护线程
        taskExecutor.setKeepAliveSeconds(keepAliveSeconds);
        taskExecutor.setThreadNamePrefix(threadNamePrefix);
        taskExecutor.setRejectedExecutionHandler(rejectedExecutionHandler);
        taskExecutor.initialize();//线程池初始化
        return taskExecutor;
    }
}

线程池参数配置类

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

/**
 * @author qf
 * @since 2024/08/31
 */
@Component
@ConfigurationProperties(prefix = "thread-pool-config.timer")
@Data
public class TimerThreadPoolConfig {

    private Integer coreSize;
    private Integer maxSize;
    private Integer queueCapacity;
    private Integer keepAliveSeconds;
}

application.yml

thread-pool-config:
  timer:
    core-size: 8
    max-size: 16
    queue-capacity: 64
    keep-alive-seconds: 180

标签:状态,Java,创建,任务,线程,taskExecutor,import
From: https://blog.csdn.net/weixin_46425661/article/details/141507582

相关文章

  • Java性能优化传奇之旅--Java万亿级性能优化之Java 性能优化逆袭:常见错误不再是阻碍
           ......
  • java线程池
    线程池接口:ExecutorService创建线程池ThreadPoolExecutorpublicThreadPoolExecutro(intcorePoolSize,//正式工intmaximumPollSize,//最大员工longkeepAliveTime,//存活时间TimeUnitunit,//TimeUnit.SECONDSBlockingQueueworkQueue,//newArrayBlockingQ......
  • Java 反射获得构造方法
        ConstructorExercisepackageConstructorExercise20240831;importClassReflect20240831.Student;importjava.lang.reflect.Constructor;importjava.lang.reflect.InvocationTargetException;publicclassCreateInstance{publicstaticvoidmain......
  • Java缓存机制:Ehcache与Guava Cache的比较
    Java缓存机制:Ehcache与GuavaCache的比较大家好,我是微赚淘客返利系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!在Java应用中,缓存是一种常见的用于提高性能和减少延迟的技术。Ehcache和GuavaCache是两个流行的Java缓存库。本文将对这两个库进行比较,并展示如何在Java中使用......
  • Java并发工具类:深入理解Concurrent包
    Java并发工具类:深入理解Concurrent包大家好,我是微赚淘客返利系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!在Java并发编程中,java.util.concurrent包(通常称为Concurrent包)提供了广泛的并发原语和组件,以帮助开发者编写高效、可伸缩和线程安全的并发程序。本文将深入探讨Conc......
  • Java数据库事务管理:ACID属性的实现与应用
    Java数据库事务管理:ACID属性的实现与应用大家好,我是微赚淘客返利系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!在现代软件开发中,数据库事务管理是确保数据一致性和完整性的关键。ACID属性是事务处理的基石,包括原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久......
  • Java异步编程:CompletableFuture与Future的对比
    Java异步编程:CompletableFuture与Future的对比大家好,我是微赚淘客返利系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!在Java中,异步编程是一种常见的编程范式,用于提高应用程序的响应性和吞吐量。Java提供了多种异步编程工具,其中Future和CompletableFuture是两个重要的接口。......
  • Java服务端监控:Prometheus与Grafana的集成
    Java服务端监控:Prometheus与Grafana的集成大家好,我是微赚淘客返利系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!在现代Java应用中,服务端监控是确保应用稳定性和性能的关键。Prometheus是一个开源的系统监控和警报工具,而Grafana是一个跨平台的开源分析和监控解决方案。将这......
  • Java服务端容器化:Docker与Kubernetes的应用
    Java服务端容器化:Docker与Kubernetes的应用大家好,我是微赚淘客返利系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!随着微服务架构和云原生技术的发展,容器化已经成为Java服务端应用部署和管理的主流方式。Docker和Kubernetes作为容器化技术的核心工具,它们为Java应用提供了灵......
  • 深入理解Java内存模型:对并发编程的影响
    深入理解Java内存模型:对并发编程的影响大家好,我是微赚淘客返利系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!在Java并发编程中,内存模型是一个至关重要的概念,它定义了程序中各个变量的访问规则,以及在多线程环境下如何正确地处理这些变量。Java内存模型(JMM)是Java规范中定义的......