iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >SpringBoot线程池和Java线程池怎么使用
  • 682
分享到

SpringBoot线程池和Java线程池怎么使用

2023-07-06 01:07:55 682人浏览 八月长安
摘要

这篇文章主要介绍“SpringBoot线程池和Java线程池怎么使用”,在日常操作中,相信很多人在springBoot线程池和Java线程池怎么使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”SpringB

这篇文章主要介绍“SpringBoot线程池和Java线程池怎么使用”,在日常操作中,相信很多人在springBoot线程池和Java线程池怎么使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”SpringBoot线程池和Java线程池怎么使用”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

    SpringBoot线程池和Java线程池的用法和实现原理

    使用默认的线程池

    方式一:通过@Async注解调用

    public class AsyncTest {    @Async    public void async(String name) throws InterruptedException {        System.out.println("async" + name + " " + Thread.currentThread().getName());        Thread.sleep(1000);    }}

    启动类上需要添加@EnableAsync注解,否则不会生效。

    @SpringBootApplication//@EnableAsyncpublic class Test1Application {   public static void main(String[] args) throws InterruptedException {      ConfigurableApplicationContext run = SpringApplication.run(Test1Application.class, args);      AsyncTest bean = run.getBean(AsyncTest.class);      for(int index = 0; index <= 10; ++index){         bean.async(String.valueOf(index));      }   }}

    方式二:直接注入 ThreadPoolTaskExecutor

    此时可不加 @EnableAsync注解

    @SpringBootTestclass Test1ApplicationTests {   @Resource   ThreadPoolTaskExecutor threadPoolTaskExecutor;   @Test   void contextLoads() {      Runnable runnable = () -> {         System.out.println(Thread.currentThread().getName());      };      for(int index = 0; index <= 10; ++index){         threadPoolTaskExecutor.submit(runnable);      }   }}

    线程池默认配置信息

    SpringBoot线程池的常见配置:

    spring:  task:    execution:      pool:        core-size: 8        max-size: 16                          # 默认是 Integer.MAX_VALUE        keep-alive: 60s                       # 当线程池中的线程数量大于 corePoolSize 时,如果某线程空闲时间超过keepAliveTime,线程将被终止        allow-core-thread-timeout: true       # 是否允许核心线程超时,默认true        queue-capacity: 100                   # 线程队列的大小,默认Integer.MAX_VALUE      shutdown:        await-termination: false              # 线程关闭等待      thread-name-prefix: task-               # 线程名称的前缀

    SpringBoot 线程池的实现原理

    TaskExecutionAutoConfiguration 类中定义了 ThreadPoolTaskExecutor,该类的内部实现也是基于java原生的 ThreadPoolExecutor类。initializeExecutor()方法在其父类中被调用,但是在父类中 RejectedExecutionHandler 被定义为了 private RejectedExecutionHandler rejectedExecutionHandler = new ThreadPoolExecutor.AbortPolicy(); ,并通过initialize()方法将AbortPolicy传入initializeExecutor()中。

    注意在TaskExecutionAutoConfiguration 类中,ThreadPoolTaskExecutor类的bean的名称为: applicationTaskExecutor 和 taskExecutor

    // TaskExecutionAutoConfiguration#applicationTaskExecutor()@Lazy@Bean(name = { APPLICATION_TASK_EXECUTOR_BEAN_NAME,      AsyncAnnotationBeanPostProcessor.DEFAUL          T_TASK_EXECUTOR_BEAN_NAME })@ConditionalOnMissingBean(Executor.class)public ThreadPoolTaskExecutor applicationTaskExecutor(TaskExecutorBuilder builder) {   return builder.build();}
    // ThreadPoolTaskExecutor#initializeExecutor()@Overrideprotected ExecutorService initializeExecutor(      ThreadFactory threadFactory, RejectedExecutionHandler rejectedExecutionHandler) {   BlockingQueue<Runnable> queue = createQueue(this.queueCapacity);   ThreadPoolExecutor executor;   if (this.taskDecorator != null) {      executor = new ThreadPoolExecutor(            this.corePoolSize, this.maxPoolSize, this.keepAliveSeconds, TimeUnit.SECONDS,            queue, threadFactory, rejectedExecutionHandler) {         @Override         public void execute(Runnable command) {            Runnable decorated = taskDecorator.decorate(command);            if (decorated != command) {               decoratedTaskMap.put(decorated, command);            }            super.execute(decorated);         }      };   }   else {      executor = new ThreadPoolExecutor(            this.corePoolSize, this.maxPoolSize, this.keepAliveSeconds, TimeUnit.SECONDS,            queue, threadFactory, rejectedExecutionHandler);   }   if (this.allowCoreThreadTimeOut) {      executor.allowCoreThreadTimeOut(true);   }   this.threadPoolExecutor = executor;   return executor;}
    // ExecutorConfigurationSupport#initialize()public void initialize() {   if (logger.isInfoEnabled()) {      logger.info("Initializing ExecutorService" + (this.beanName != null ? " '" + this.beanName + "'" : ""));   }   if (!this.threadNamePrefixSet && this.beanName != null) {      setThreadNamePrefix(this.beanName + "-");   }   this.executor = initializeExecutor(this.threadFactory, this.rejectedExecutionHandler);}

    覆盖默认的线程池

    覆盖默认的 taskExecutor对象,bean的返回类型可以是ThreadPoolTaskExecutor也可以是Executor

    @Configurationpublic class ThreadPoolConfiguration {    @Bean("taskExecutor")    public ThreadPoolTaskExecutor taskExecutor() {        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();        //设置线程池参数信息        taskExecutor.setCorePoolSize(10);        taskExecutor.setMaxPoolSize(50);        taskExecutor.setQueueCapacity(200);        taskExecutor.seTKEepAliveSeconds(60);        taskExecutor.setThreadNamePrefix("myExecutor--");        taskExecutor.setWaitForTasksToCompleteOnShutdown(true);        taskExecutor.setAwaitTerminationSeconds(60);        //修改拒绝策略为使用当前线程执行        taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());        //初始化线程池        taskExecutor.initialize();        return taskExecutor;    }}

    管理多个线程池

    如果出现了多个线程池,例如再定义一个线程池 taskExecutor2,则直接执行会报错。此时需要指定bean的名称即可。

    @Bean("taskExecutor2")public ThreadPoolTaskExecutor taskExecutor2() {    ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();    //设置线程池参数信息    taskExecutor.setCorePoolSize(10);    taskExecutor.setMaxPoolSize(50);    taskExecutor.setQueueCapacity(200);    taskExecutor.setKeepAliveSeconds(60);    taskExecutor.setThreadNamePrefix("myExecutor2--");    taskExecutor.setWaitForTasksToCompleteOnShutdown(true);    taskExecutor.setAwaitTerminationSeconds(60);    //修改拒绝策略为使用当前线程执行    taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());    //初始化线程池    taskExecutor.initialize();    return taskExecutor;}

    引用线程池时,需要将变量名更改为bean的名称,这样会按照名称查找。

    @ResourceThreadPoolTaskExecutor taskExecutor2;

    对于使用@Async注解的多线程则在注解中指定bean的名字即可。

    @Async("taskExecutor2")    public void async(String name) throws InterruptedException {        System.out.println("async" + name + " " + Thread.currentThread().getName());        Thread.sleep(1000);    }

    线程池的四种拒绝策略

    JAVA常用的四种线程池

    ThreadPoolExecutor 类的构造函数如下:

    public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,                          BlockingQueue<Runnable> workQueue) {    this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,         Executors.defaultThreadFactory(), defaultHandler);}

    newCachedThreadPool

    不限制最大线程数(maximumPoolSize=Integer.MAX_VALUE),如果有空闲的线程超过需要,则回收,否则重用已有的线程。

    new ThreadPoolExecutor(0, Integer.MAX_VALUE,                              60L, TimeUnit.SECONDS,                              new SynchronousQueue<Runnable>());

    newFixedThreadPool

    定长线程池,超出线程数的任务会在队列中等待。

    return new ThreadPoolExecutor(nThreads, nThreads,                              0L, TimeUnit.MILLISECONDS,                              new LinkedBlockingQueue<Runnable>());

    newScheduledThreadPool

    类似于newCachedThreadPool,线程数无上限,但是可以指定corePoolSize。可实现延迟执行、周期执行。

    public ScheduledThreadPoolExecutor(int corePoolSize) {    super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,          new DelayedWorkQueue());}

    周期执行:

    ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);scheduledThreadPool.scheduleAtFixedRate(()->{   System.out.println("rate");}, 1, 1, TimeUnit.SECONDS);

    延时执行:

    scheduledThreadPool.schedule(()->{   System.out.println("delay 3 seconds");}, 3, TimeUnit.SECONDS);

    newSingleThreadExecutor

    单线程线程池,可以实现线程的顺序执行。

    public static ExecutorService newSingleThreadExecutor() {    return new FinalizableDelegatedExecutorService        (new ThreadPoolExecutor(1, 1,                                0L, TimeUnit.MILLISECONDS,                                new LinkedBlockingQueue<Runnable>()));}

    Java 线程池中的四种拒绝策略

    • CallerRunsPolicy:线程池让调用者去执行。

    • AbortPolicy:如果线程池拒绝了任务,直接报错。

    • DiscardPolicy:如果线程池拒绝了任务,直接丢弃。

    • DiscardOldestPolicy:如果线程池拒绝了任务,直接将线程池中最旧的,未运行的任务丢弃,将新任务入队。

    CallerRunsPolicy

    直接在主线程中执行了run方法。

    public static class CallerRunsPolicy implements RejectedExecutionHandler {     public CallerRunsPolicy() { }     public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {        if (!e.isshutdown()) {            r.run();        }    }}

    效果类似于:

    Runnable thread = ()->{   System.out.println(Thread.currentThread().getName());   try {      Thread.sleep(0);   } catch (InterruptedException e) {      throw new RuntimeException(e);   }};thread.run();

    AbortPolicy

    直接抛出RejectedExecutionException异常,并指示任务的信息,线程池的信息。、

    public static class AbortPolicy implements RejectedExecutionHandler {     public AbortPolicy() { }     public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {        throw new RejectedExecutionException("Task " + r.toString() +                                             " rejected from " +                                             e.toString());    }}

    DiscardPolicy

    什么也不做。

    public static class DiscardPolicy implements RejectedExecutionHandler {     public DiscardPolicy() { }     public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {    }}

    DiscardOldestPolicy

    • e.getQueue().poll() : 取出队列最旧的任务。

    • e.execute(r) : 当前任务入队。

    public static class DiscardOldestPolicy implements RejectedExecutionHandler {     public DiscardOldestPolicy() { }     public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {        if (!e.isShutdown()) {            e.getQueue().poll();            e.execute(r);        }    }}

    Java 线程复用的原理

    java的线程池中保存的是 java.util.concurrent.ThreadPoolExecutor.Worker 对象,该对象在 被维护在private final HashSet<Worker> workers = new HashSet<Worker>();workQueue是保存待执行的任务的队列,线程池中加入新的任务时,会将任务加入到workQueue队列中。

    private final class Worker    extends AbstractQueuedSynchronizer    implements Runnable{        private static final long serialVersionUID = 6138294804551838833L;        final Thread thread;        Runnable firstTask;        volatile long completedTasks;        Worker(Runnable firstTask) {        setState(-1); // inhibit interrupts until runWorker        this.firstTask = firstTask;        this.thread = getThreadFactory().newThread(this);    }        public void run() {        runWorker(this);    }    // Lock methods    //    // The value 0 represents the unlocked state.    // The value 1 represents the locked state.    protected boolean isHeldExclusively() {        return getState() != 0;    }    protected boolean tryAcquire(int unused) {        if (compareAndSetState(0, 1)) {            setExclusiveOwnerThread(Thread.currentThread());            return true;        }        return false;    }    protected boolean tryRelease(int unused) {        setExclusiveOwnerThread(null);        setState(0);        return true;    }    public void lock()        { acquire(1); }    public boolean tryLock()  { return tryAcquire(1); }    public void unlock()      { release(1); }    public boolean isLocked() { return isHeldExclusively(); }    void interruptIfStarted() {        Thread t;        if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) {            try {                t.interrupt();            } catch (SecurityException ignore) {            }        }    }}

    work对象的执行依赖于 runWorker(),与我们平时写的线程不同,该线程处在一个循环中,并不断地从队列中获取新的任务执行。因此线程池中的线程才可以复用,而不是像我们平常使用的线程一样执行完毕就结束。

    final void runWorker(Worker w) {    Thread wt = Thread.currentThread();    Runnable task = w.firstTask;    w.firstTask = null;    w.unlock(); // allow interrupts    boolean completedAbruptly = true;    try {        while (task != null || (task = getTask()) != null) {            w.lock();            // If pool is stopping, ensure thread is interrupted;            // if not, ensure thread is not interrupted.  This            // requires a recheck in second case to deal with            // shutdownNow race while clearing interrupt            if ((runStateAtLeast(ctl.get(), STOP) ||                 (Thread.interrupted() &&                  runStateAtLeast(ctl.get(), STOP))) &&                !wt.isInterrupted())                wt.interrupt();            try {                beforeExecute(wt, task);                Throwable thrown = null;                try {                    task.run();                } catch (RuntimeException x) {                    thrown = x; throw x;                } catch (Error x) {                    thrown = x; throw x;                } catch (Throwable x) {                    thrown = x; throw new Error(x);                } finally {                    afterExecute(task, thrown);                }            } finally {                task = null;                w.completedTasks++;                w.unlock();            }        }        completedAbruptly = false;    } finally {        processWorkerExit(w, completedAbruptly);    }}

    到此,关于“SpringBoot线程池和Java线程池怎么使用”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

    --结束END--

    本文标题: SpringBoot线程池和Java线程池怎么使用

    本文链接: https://www.lsjlt.com/news/356939.html(转载时请注明来源链接)

    有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

    本篇文章演示代码以及资料文档资料下载

    下载Word文档到电脑,方便收藏和打印~

    下载Word文档
    猜你喜欢
    • SpringBoot线程池和Java线程池怎么使用
      这篇文章主要介绍“SpringBoot线程池和Java线程池怎么使用”,在日常操作中,相信很多人在SpringBoot线程池和Java线程池怎么使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”SpringB...
      99+
      2023-07-06
    • SpringBoot线程池和Java线程池的使用和实现原理解析
      目录SpringBoot线程池和Java线程池的用法和实现原理使用默认的线程池方式一:通过@Async注解调用方式二:直接注入 ThreadPoolTaskExecutor...
      99+
      2023-05-15
      SpringBoot线程池和Java线程池用法 SpringBoot线程池
    • Java线程池怎么用
      小编给大家分享一下Java线程池怎么用,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!一、什么是线程池?线程池是一种用于实现计算机程序并发执行的软件设计模式。线程池...
      99+
      2023-06-15
    • java怎么使用线程池启动多线程
      在 Java 中,可以使用线程池来启动多线程。以下是使用线程池启动多线程的示例代码:首先,需要导入 `java.util.concu...
      99+
      2023-09-15
      java
    • 线程池是什么?线程池(ThreadPoolExecutor)使用详解
      点一点,了解更多https://www.csdn.net/ 本篇文章将详细讲解什么是线程池,线程池的参数介绍,线程池的工作流程,使用Executors创建常见的线程池~~~ 目录 点一点,了解更多 文章目录 一、线程池的概念 1.1线...
      99+
      2023-09-03
      java 数据结构 jvm 面试 java-ee
    • python中ThreadPoolExecutor线程池和ProcessPoolExecutor进程池怎么使用
      这篇文章主要介绍了python中ThreadPoolExecutor线程池和ProcessPoolExecutor进程池怎么使用的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇python中ThreadPoolE...
      99+
      2023-07-02
    • springboot使用线程池(ThreadPoolTaskExecutor)示例
      目录线程池创建线程池参数线程池测试1(核心线程数量)线程池测试2(当核心线程数量和最大线程数量不够时)总结代码仓库:gitee 线程池创建 @Configuration @Enab...
      99+
      2024-04-02
    • SpringBoot实现线程池
      现在由于系统越来越复杂,导致很多接口速度变慢,这时候就会想到可以利用线程池来处理一些耗时并不影响系统的操作。 新建Spring Boot项目 1. ExecutorConfig....
      99+
      2024-04-02
    • springboot自帶线程池ThreadPoolTaskExecutor使用
      不管是阿里,还是华为java开发手册,都会有一条建议,就是让开发者不要使用Executors去创建线程池,而是使用构造函数ThreadPoolExecutor的方式来创建,并设置合理...
      99+
      2023-05-14
      springboot自帶线程池ThreadPoolTaskExecutor springboot ThreadPoolTaskExecutor
    • Springboot自带线程池
      一: ThreadPoolTaskExecuto 1 ThreadPoolTaskExecutor线程池: ThreadPoolTaskExecutor是Spring基于java本身的线程池ThreadPoolExecutor做的二次封装,...
      99+
      2023-09-14
      spring boot java spring
    • java怎么从线程池获取线程
      在 Java 中,可以使用 `ExecutorService` 接口来管理线程池,并从线程池中获取线程。下面是通过线程池获取线程的一...
      99+
      2023-10-11
      java
    • 图文详解Java线程和线程池
      目录一、什么是线程,线程和进程的区别是什么二、线程中的基本概念,线程的生命周期三、单线程和多线程四,线程池的原理解析五,常见的几种线程池的特点以及各自的应用场景总结一、什么是线程,线...
      99+
      2024-04-02
    • springboot使用线程池方法是什么
      本篇内容主要讲解“springboot使用线程池方法是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“springboot使用线程池方法是什么”吧!线程池创建@Configuration@En...
      99+
      2023-06-22
    • Java线程池怎么使用AbortPolicy策略
      本篇内容介绍了“Java线程池怎么使用AbortPolicy策略”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!线程池ThreadPoolEx...
      99+
      2023-07-02
    • Java并发之怎么使用线程池
      这篇文章主要介绍“Java并发之怎么使用线程池”,在日常操作中,相信很多人在Java并发之怎么使用线程池问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java并发之怎么使用线程池”的疑惑有所帮助!接下来,请跟...
      99+
      2023-06-16
    • java线程池ThreadPoolExecutor类怎么用
      这篇文章将为大家详细讲解有关java线程池ThreadPoolExecutor类怎么用,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。在《阿里巴巴java开发手册》中指出了线程资源必须通过线程池提供,不允许...
      99+
      2023-06-29
    • Java手写线程池之向JDK线程池进发
      目录前言JDK线程池一瞥自己动手实现线程池线程池参数介绍实现Runnable实现Callable拒绝策略的实现线程池关闭实现工作线程的工作实现线程池实现的BUG完整代码线程池测试总结...
      99+
      2022-11-13
      Java手写线程池 Java线程池
    • 怎么使用Node实现轻量化进程池和线程池
      今天小编给大家分享一下怎么使用Node实现轻量化进程池和线程池的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们...
      99+
      2024-04-02
    • java怎么停止线程池中的线程
      要停止线程池中的线程,可以使用 `ExecutorService` 接口提供的 `shutdown()` 方法来停止线程池。这个方法...
      99+
      2023-08-20
      java
    • 怎么在Java中使用线程工厂监控线程池
      这期内容当中小编将会给大家带来有关怎么在Java中使用线程工厂监控线程池,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。ThreadFactory线程池中的线程从哪里来呢?就是ThreadFoctorypu...
      99+
      2023-06-14
    软考高级职称资格查询
    编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
    • 官方手机版

    • 微信公众号

    • 商务合作