首頁 > Java > java教程 > Springboot自帶線程池怎麼實現

Springboot自帶線程池怎麼實現

王林
發布: 2023-06-28 16:33:05
轉載
932 人瀏覽過

一: ThreadPoolTask​​Executo

1 ThreadPoolTask​​Executor執行緒池:

ThreadPoolTask​​Executor是Spring基於java本身的執行緒池ThreadPoolExecutor所做的二次封裝,主要目的還是為了更方便的在spring框架體系中使用執行緒池, 是Spring中預設的執行緒池

2 使用ThreadPoolTask​​Executor注入bean到ioc中
  設定檔形式,Spring會自動設定

## 默认线程池配置,ThreadPoolTaskExecutor 
# 核心线程数
spring.task.execution.pool.core-size=8  
# 最大线程数
spring.task.execution.pool.max-size=16
# 空闲线程存活时间
spring.task.execution.pool.keep-alive=60s
# 是否允许核心线程超时
spring.task.execution.pool.allow-core-thread-timeout=true
# 线程队列数量
spring.task.execution.pool.queue-capacity=100
# 线程关闭等待
spring.task.execution.shutdown.await-termination=false
spring.task.execution.shutdown.await-termination-period=
# 线程名称前缀
spring.task.execution.thread-name-prefix=demo_Thread
登入後複製

設定形式:

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledFuture;
//@Configuration
public class ThreadConfig {
    @Value("${task.maxPoolSize}")
    private int maxPoolSize;
    //todo 其他的相关配置都可以通过配置文件中注入
    @Bean("ThreadPoolTaskExecutor")
    public Executor myAsync() {
        final ThreadPoolTaskExecutor executor =
                new ThreadPoolTaskExecutor();
        executor.setMaxPoolSize(maxPoolSize);
        //todo  其他参数设置
        //初始化
        executor.initialize();
        return executor;
    }
}
登入後複製

3 創建線程後全部從ioc中獲取線程池子

4 線程池處理流程:

(1) 查看核心線程池是否已滿,不滿就創建一條線程執行任務,核心執行緒數量已滿就查看任務佇列是否已滿不滿就將執行緒儲存在任務佇列中任務佇列已滿,就查看最大執行緒數量,不滿就創建執行緒執行任務,已滿就按照拒絕策略執行

(2) 拒絕策略:

  • CallerRunsPolicy():原來的執行緒執行

  • ##AbortPolicy():直接拋出例外

  • DiscardPolicy():直接丟棄

  • #DiscardOldestPolicy():丟棄佇列中最老的任

#二: ThreadPoolTask​​Scheduler 

1 ThreadPoolTask​​Scheduler 定時調度任務執行緒池,處理非同步任務

2 使用方式: 注入ThreadPoolTask​​Scheduler的bean

 (1) 設定檔形式: ..

 (2) 設定類別形式:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ScheduledFuture;
@Configuration
public class ThreadPoolTaskSchedulerConfig {
    @Bean
    public ThreadPoolTaskScheduler threadPoolTaskScheduler() {
        final ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
        //设置等待任务在关机时l候完成
        threadPoolTaskScheduler.setWaitForTasksToCompleteOnShutdown(true);
        //设置等待时间为60s
        threadPoolTaskScheduler.setAwaitTerminationSeconds(60);
        return threadPoolTaskScheduler;
    }
}
登入後複製

3  使用ThreadPoolTask​​Scheduler定時任務

做普通執行緒池使用:

  •  submit( callable),需要執行結果

  •  submit(runnable),不需要執行結果

(1) 定時任務

#新增任務內容Runnable,設定執行週期Trigger/Date,Trigger表達式百度即可

 schedule(Runnable task,Trigger)
 schedule(Runnable task,Date)
登入後複製

(2) 指定間隔時間執行一次任務,時間間隔是前一次任務完成到下一次任務開始,單位毫秒

 scheduleWithFixedDelay(Runnable task,long delay)
登入後複製

(3) 固定頻率執行任務,在任務開始後間隔一段時間執行新的任務,如果上次任務麼執行完成,則等待上次任務執行完成後執行下次任務

 scheduleAtFixedRate(Runnable task,long delay)
登入後複製

(4) 定時任務取消:

設定定時任務儲存的集合,定時任務執行的結果為ScheduledFuture,將該物件儲存到集合,透過在集合中取得ScheduledFuture< ?>物件.cancel(true)取消定時任務

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Service;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.*;
@Service
public class SchedulerService {
    @Autowired
    ThreadPoolTaskScheduler scheduler;
    /**
     * 常规线程池使用
     */
    public void tesScheduler1() throws ExecutionException, InterruptedException {
        //无返回值
        final Future<?> demo_scheduler1 = scheduler.submit(new Runnable() {
            @Override
            public void run() {
                System.out.println("demo runnable scheduler");
            }
        });
        //无返回值
        final Future<?> demo_scheduler2 = scheduler.submit(new Callable<Object>() {
            @Override
            public Object call() throws Exception {
                System.out.println("demo callable  scheduler");
                return "callable";
            }
        });
        System.out.println("result:" + demo_scheduler2.get());
    }
    /**
     * 定时任务
     */
    public void tesScheduler2() throws ParseException {
        //CronTrigger表达式百度即可
        scheduler.schedule(() -> {
            System.out.println("定时任务");
        }, new CronTrigger("0/1****?"));
        //创建指定时间的日期
        final Date date = new Date(2023, 3, 26, 21, 35);
        final DateFormat format = new SimpleDateFormat();
        final Date parse = format.parse("2023-03-26-21-26");
        scheduler.schedule(() -> {
            System.out.println(new Date());
        }, parse);
    }
    /**
     * 指定时间间隔执行任务,上次任务结束到下次任务开始的时间间隔
     */
    public void tesScheduler3() {
        scheduler.scheduleWithFixedDelay(() -> {
            //todo
        }, 300L);
    }
    /**
     * 固定频率执行任务,在固定一段时间后便会执行下次任务,
     * 如果时间到了上次任务还没执行完毕则等待,
     * 直到上一次任务执行完毕后立马执行下次任务
     */
    public void tesScheduler4() {
        scheduler.scheduleAtFixedRate(new FutureTask<String>(new Callable<String>() {
                    @Override
                    public String call() throws Exception {
                        return null;
                    }
                }),
                200);
    }
    //取消定时任务队列
    public static ConcurrentMap<String, ScheduledFuture> map = new ConcurrentHashMap<>();
    public void startTask(String k1) {
        map.compute(k1, (k, v) -> {
            if (map.containsKey(k)) return v;
            map.put(k, v);
            return v;
        });
    }
}
登入後複製

三@Scheduled實現定時任務,註解開啟定時任務

1 使用@EnableScheduled開啟支援

2 @ Scheduled標註方法

 (1)@Scheduled(fixedDelay=5000)延遲執行,5s後執行

 (2)@Scheduled(fixedRate=5000)定時執行,每隔五秒就進行執行
 (3)@Scheduled(corn="002**?") 自訂執行,corn表達式百度,常用此執行方式,corn="002**?"每天凌晨兩點開始執行定時任務

3 注意@Scheduled開啟的任務是單線程的,容易阻塞

 (1) 在ioc中註入ThreadPoolTask​​Scheduler,則Scheduled就使用ThreadPoolTask​​Scheduler執行緒池,可以解決單執行緒阻塞問題

 ( 2) @Scheduled和@Async註解開啟定時任務,在@Async("pool")中指定線程池,若是沒有指定線程池會使用Spring的SimpleAsyncTaskExecutor線程池,這個線程池每次都會增加一個線程去執行任務,效率低

四:Spring中的非同步任務

1 @EnableAsync開啟非同步支援

2 @Async開啟非同步任務,指定執行緒池

#注意:@ Scheduled和@Async註解開啟定時任務,在@Async("pool")中指定線程池,若是沒有指定線程池會使用Spring的SimpleAsyncTaskExecutor線程池,這個線程池每次都會增加一個線程去執行任務,效率低下但是@Async單獨開啟非同步任務,則使用的是預設的執行緒池,建議根據需求自訂執行緒池

注意:@Async的回傳值只能為void或Future, 呼叫方和@Async不能在一個類別中,否則不走aop;

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
@Service
public class AsyncService {
    @Async
    public void showThreadName1() {
        //默认线程池
        System.out.println(Thread.currentThread().getName());
    }
    @Async("myPool")//指定线程池
    public void showThreadName2() {
        System.out.println(Thread.currentThread().getName());
    }
}
登入後複製

五:獻上一顆自java自訂線程池:

 @Bean("myPool")
    public Executor executor(){
       return new ThreadPoolExecutor(// 自定义一个线程池
                1, // coreSize
                2, // maxSize
                60, // 60s
                TimeUnit.SECONDS, new ArrayBlockingQueue<>(3) // 有界队列,容量是3个
                , Executors.defaultThreadFactory()
                , new ThreadPoolExecutor.AbortPolicy());
    }
登入後複製
java自帶的線程池,快取,固定數量的,單線程的,定時的,,,,六七種,後面續上

以上是Springboot自帶線程池怎麼實現的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:yisu.com
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板