Springboot 独自のスレッド プールを実装する方法

王林
リリース: 2023-06-28 16:33:05
転載
876 人が閲覧しました

1: ThreadPoolTask​​Executo

1 ThreadPoolTask​​Executor スレッド プール:

ThreadPoolTask​​Executor は、Java 独自のスレッド プール ThreadPoolExecutor に基づく Spring の二次カプセル化です。主な目的は、Spring フレームワーク システムでより便利にすることです。スレッド プールは Spring で使用されます。これは Spring のデフォルトのスレッド プールです。

2 ThreadPoolTask​​Executor を使用して、ioc
構成ファイル フォームに Bean を注入します。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
ログイン後にコピー

Configuration フォームを構成します。 :

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(): キュー内の最も古いアイテムを破棄します

  • ##2: 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 を追加し、実行期間のトリガー/日付を設定します。トリガー式は Baidu を使用できます。

 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;
        });
    }
}
ログイン後にコピー

Three @Scheduled はスケジュールされたタスクを実装し、アノテーションによりスケジュールされたタスクが有効になります

1 @EnableScheduled を使用してサポートを有効にします

2 @ Scheduledアノテーションメソッド

(1)@Scheduled(fixedDelay=5000) 遅延実行、5秒後に実行

(2)@Scheduled(fixedRate=5000) スケジュールされた実行、5秒ごとに実行

(3) @Scheduled(corn="002**?") カスタム実行、コーン式 Baidu、この実行方法は一般的に使用され、corn="002**?" は毎日午前 2 時にスケジュールされたタスクの実行を開始します


3 @Scheduled によって開始されたタスクはシングルスレッドであり、ブロックされやすいことに注意してください。

(1) ThreadPoolTask​​Scheduler を ioc に挿入すると、Scheduled は ThreadPoolTask​​Scheduler スレッド プールを使用します。これにより、シングルスレッドの問題を解決できます。スレッド ブロックの問題

( 2) @Scheduled アノテーションと @Async アノテーションによりスケジュールされたタスクが有効になり、@Async("pool") でスレッド プールを指定します。スレッド プールが指定されていない場合は、Spring の SimpleAsyncTaskExecutor スレッド プールが使用されます。プールはタスクを実行するたびにスレッドを追加します。効率が低くなります。

4: 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());
    }
}
ログイン後にコピー

5: 現在カスタム 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 独自のスレッド プール、キャッシュ、固定数、単一スレッド、時間指定、、、、6 または 7 種類、続き

以上がSpringboot 独自のスレッド プールを実装する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:yisu.com
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!