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 條記錄的后端作業,因為它會創建更大的數量每個任務都有多個線程,您肯定會遇到內存問題。

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));
添加回答
舉報