亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

Spring - 添加低優先級多線程服務(對生產性能沒有影響)

Spring - 添加低優先級多線程服務(對生產性能沒有影響)

holdtom 2023-07-19 16:11:54
我們有一個 Spring 應用程序,我想添加一個服務,該服務將使用多個線程處理 10Ks ID,但將作為后臺進程而不影響生產實時性。服務將更新數據庫并發送外部提供商請求。我不希望服務影響生產性能/計時,我想以低優先級對每個 ID 執行操作我希望對超出此特定執行器范圍的所有其他線程設置低優先級。答案使用ThreadPoolExecutor與我的案例更相關嗎?ThreadPoolExecutor threadPool = new ThreadPoolExecutor(1, numOfWorkerThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());threadPool.setThreadFactory(new OpJobThreadFactory(Thread.NORM_PRIORITY-2));public final static class OpJobThreadFactory implements ThreadFactory {?private int priority;?public OpJobThreadFactory(int priority) {? this(priority, true);}@Overridepublic Thread newThread(Runnable r) {? Thread t = new Thread(r, namePrefix + threadNumber.getAndIncrement());? t.setDaemon(daemon);? t.setPriority(priority);?}}也許甚至使用Thread.MIN_PRIORITY或者我可以使用Executors.newCachedThreadPool()創建一個線程池,該線程池根據需要創建新線程,但會重用以前構造的線程(當它們可用時)。這些池通常會提高執行許多短期異步任務的程序的性能。我還應該使用Spring bean嗎?因為我需要按需/請求創建池,所以似乎不需要/錯誤編輯?我應該使用Spring Actuator來獲取此任務還是其他監控工具?Spring Boot Actuator 模塊通過提供健康檢查、審計、指標收集、HTTP 跟蹤等生產就緒功能來幫助您監控和管理 Spring Boot 應用程序。所有這些功能都可以通過 JMX 或 HTTP 端點訪問。
查看完整描述

2 回答

?
達令說

TA貢獻1821條經驗 獲得超6個贊

我想澄清一下這個問題

什么是線程優先級?根據 java SE 文檔

每個線程都有一個優先級。具有較高優先級的線程優先于具有較低優先級的線程執行。

即使您創建具有優先級的線程,它也不能完全保證優先級較低的線程首先執行,您可能必須阻塞優先級較低的線程,直到執行其他線程

對于小型 java 程序,您可以自己處理線程執行,但對于較大的程序,建議您使用 vanilla Java 中的 Executor Framework(來自 java.util.concurrent 包)或使用 spring TaskExecutor。通過使用這兩個框架,您可以異步執行任務,即作為主任務的一部分在后臺執行它們。

對生產的影響:

例如,主要任務將是調用您的其余端點(即/account),并在調用帳戶端點時您想要向客戶發送歡迎電子郵件,這是第三方 API 調用,可以使用 Executor Framework 或 Spring 異步執行TaskExecutor 異步執行它們,即作為后臺進程,它們不會對當前 API 產生影響,但肯定會對生產服務器產生影響,因為您在同一個 JVM 中運行線程并且它們共享公共內存。如果創建了許多線程但沒有銷毀,那么服務器肯定會崩潰。

因此,使用 Executor Framework 或 Spring TaskExecutor 并不能保證它不會影響您當前的生產,它肯定會提高所調用的其余 API 的性能。因為它是異步執行的并且關于您的其他問題

我可以使用 Executors.newCachedThreadPool()

是的,如果您有許多短期任務,例如更新數據庫中的單個列或僅觸發一次休息端點,并且它不適合批量加載或執行某些更新 10000 條記錄的后端作業,因為它會創建更大的數量每個任務都有多個線程,您肯定會遇到內存問題。

查看完整回答
反對 回復 2023-07-19
?
慕萊塢森

TA貢獻1810條經驗 獲得超4個贊

這是一種創建可配置任務“堆”并始終將主任務保留在堆頂部的方法。

總結這個過程,您應該創建一個自定義任務執行器。首先,您需要創建一個 ThreadPoolTaskExecutor?bean,并覆蓋一個方法。需要修改的屬性有:CorePoolSize(初始線程數)、QueueCapacity(隊列中等待的線程數)和MaxPoolSize(最大線程數)。使用這些參數,您可以配置應用程序限制,以使該服務不會影響生產性能。

?@Bean("CustomTaskExecutor")

? public TaskExecutor threadPoolTaskExecutor(

? ? ? ? ? @Value("${spring.async.core-pool-size}") int corePoolSize,

? ? ? ? ? @Value("${spring.async.max-pool-size}") int maxPoolSize,

? ? ? ? ? @Value("${spring.async.queue-capacity}") int queueCapacity) {

? ? ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor() {


? ? ? @Override

? ? ? protected BlockingQueue<Runnable> createQueue(int queueCapacity) {

? ? ? ? return new PriorityBlockingQueue<Runnable>(queueCapacity);

? ? ? }


? ? };

? ? executor.setCorePoolSize(corePoolSize);

? ? executor.setMaxPoolSize(maxPoolSize);

? ? executor.setQueueCapacity(queueCapacity);

? ? return executor;

? }

之后,您需要制定任務執行者可以理解的優先級。為此,我們需要創建兩個類: 1) 一個實現 Runnable 接口的自定義類,該類將運行任務 2) 一個擴展 FutureTask 并實現 Comparable 接口的包裝類,以便任務執行器可以理解任務的優先級選擇邏輯任務


public class Task implements Runnable {

? ? private Consumer<Job> jobConsumer;

? ? private Job job;

? ? ? public Job getJob() {

? ? ? ? return this.job;

? ? ? }

? ? ? public Task(Consumer<Job> jobConsumer, Job job) {

? ? ? ? this.jobConsumer = jobConsumer;

? ? ? ? this.job = job;

? ? ? }

? ? ? @Override

? ? ? public void run() {

? ? ? ? this.jobConsumer.accept(job);

? ? ? }

? ? }

然后你就有了 FutureCustomTask 類:


public class FutureCustomTask extends FutureTask<FutureCustomTask> implements Comparable<FutureCustomTask> {

private Task task;

public FutureCustomTask(Task task) {

? ? super(task, null);

? ? this.task = task;

? }

@Override

? public int compareTo(FutureCustomTask o) {

? ? return task.getJob().getPriority().compareTo(o.task.getJob().getPriority());

? }

}

為了執行任務執行器需要自動裝配。然后,您可以創建 Task 對象,將其包裝在 FutureCustomTask 中,并將其傳遞給 TaskExecutor。代碼應如下所示:


@Autowired

private TaskExecutor taskExecutor;

@Autowired

private JobBusiness jobBusiness;

...

Task task = new Task(jobBusiness::performSomethingOn, job);

taskExecutor.execute(new FutureCustomTask(task));


查看完整回答
反對 回復 2023-07-19
  • 2 回答
  • 0 關注
  • 182 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號