在多任務執行的時候,我們可能用到線程池,如果在任務量非常大的情況下任務可能走了拒絕策略,有人可能會說那就吧隊列設置成最大的,或者無界隊列的情況,這種方式是可以暫時解決任務丟失的情況,但是如果隊列如果太多一直阻塞可能會造成OOM。所以再網上看了一些文檔,在拒絕策略那總結了兩種方式,並在生產驗證了這兩種情況:
(1)直接在拒絕那重新給隊列添加任務,重複添加,直到隊列中有空位騰出
(2)在拒絕策略那塊,可以再次補償執行添加任務,直到成功爲止
代碼如下:
方式一:
package com.eebbk.content.ai.makequestion.config;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
/**
* @Auther: lipf
* @Date: 2020/1/13 16:50
* @Description:
*/
@Slf4j
public class CustomAbortPolicy implements RejectedExecutionHandler {
public void AbortPolicy() { }
/**
* Always throws RejectedExecutionException.
* @param r the runnable task requested to be executed
* @throws RejectedExecutionException always
*/
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
if (!executor.isShutdown()) {
try {
log.error("full-->>線程池已滿,執行拒絕策略");
executor.getQueue().put(r);
} catch (InterruptedException e) {
log.error("interruptedException="+e.toString());
}
}
}
}
方式二:
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
if (!executor.isShutdown()) {
try {
log.error("full-->>線程池已滿,執行拒絕策略");
while (e.getQueue().remainingCapacity() == 0);
e.execute(r);
} catch (InterruptedException e) {
log.error("interruptedException="+e.toString());
}
}
}
任務測試用例:
public void testThread(){
//模擬10000個任務執行,用計時器保證任務最終執行後合併歸一
CountDownLatch countDownLatch=new CountDownLatch(10000);
//統計任務是否丟失
AtomicInteger atomicInteger=new AtomicInteger();
//模擬10000個任務執行
for (int i = 0; i < 10000; i++) {
taskExecutor.submit(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(100);
atomicInteger.addAndGet(1);
} catch (Exception e) {
} finally {
countDownLatch.countDown();
}
}
});
}
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(atomicInteger);
}