線程池拒絕策略:優(yōu)雅處理過載請(qǐng)求
什么是線程池拒絕策略?
線程池拒絕策略是指當(dāng)線程池中的任務(wù)數(shù)量達(dá)到上限時(shí),新提交的任務(wù)如何處理的一種策略。Java 提供了幾種內(nèi)置的拒絕策略,開發(fā)者也可以自定義策略。

內(nèi)置的拒絕策略
Java 提供了以下幾種內(nèi)置的拒絕策略:
- AbortPolicy:默認(rèn)策略,直接拋出 RejectedExecutionException 異常,阻止系統(tǒng)正常運(yùn)行。
 - CallerRunsPolicy:由調(diào)用線程處理該任務(wù),既不拋棄任務(wù),也不拋出異常。
 - DiscardPolicy:直接丟棄任務(wù),不予處理。
 - DiscardOldestPolicy:丟棄最舊的任務(wù),然后嘗試重新提交被拒絕的任務(wù)。
 
下面,我們通過代碼示例來詳細(xì)講述這些策略的實(shí)現(xiàn)和應(yīng)用。
代碼示例
創(chuàng)建一個(gè)簡(jiǎn)單的線程池:
import java.util.concurrent.*;
public class ThreadPoolExample {
    private static final int CORE_POOL_SIZE = 2;
    private static final int MAX_POOL_SIZE = 4;
    private static final long KEEP_ALIVE_TIME = 10L;
    public static void main(String[] args) {
        // 使用 ArrayBlockingQueue 作為任務(wù)隊(duì)列,容量為 2
        BlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(2);
        // 創(chuàng)建線程池
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
            CORE_POOL_SIZE,
            MAX_POOL_SIZE,
            KEEP_ALIVE_TIME,
            TimeUnit.SECONDS,
            queue
        );
        // 提交任務(wù)
        for (int i = 0; i < 10; i++) {
            final int taskNumber = i + 1;
            executor.submit(() -> {
                try {
                    System.out.println("Executing task " + taskNumber);
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            });
        }
        // 關(guān)閉線程池
        executor.shutdown();
    }
}使用 AbortPolicy:
import java.util.concurrent.*;
public class AbortPolicyExample {
    public static void main(String[] args) {
        BlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(2);
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
            2, 4, 10L, TimeUnit.SECONDS, queue,
            new ThreadPoolExecutor.AbortPolicy() // 使用 AbortPolicy
        );
        for (int i = 0; i < 10; i++) {
            final int taskNumber = i + 1;
            try {
                executor.submit(() -> {
                    try {
                        System.out.println("Executing task " + taskNumber);
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                });
            } catch (RejectedExecutionException e) {
                System.err.println("Task " + taskNumber + " was rejected");
            }
        }
        executor.shutdown();
    }
}使用 CallerRunsPolicy:
import java.util.concurrent.*;
public class CallerRunsPolicyExample {
    public static void main(String[] args) {
        BlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(2);
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
            2, 4, 10L, TimeUnit.SECONDS, queue,
            new ThreadPoolExecutor.CallerRunsPolicy() // 使用 CallerRunsPolicy
        );
        for (int i = 0; i < 10; i++) {
            final int taskNumber = i + 1;
            executor.submit(() -> {
                System.out.println("Executing task " + taskNumber);
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            });
        }
        executor.shutdown();
    }
}使用 DiscardPolicy:
import java.util.concurrent.*;
public class DiscardPolicyExample {
    public static void main(String[] args) {
        BlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(2);
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
            2, 4, 10L, TimeUnit.SECONDS, queue,
            new ThreadPoolExecutor.DiscardPolicy() // 使用 DiscardPolicy
        );
        for (int i = 0; i < 10; i++) {
            final int taskNumber = i + 1;
            executor.submit(() -> {
                System.out.println("Executing task " + taskNumber);
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            });
        }
        executor.shutdown();
    }
}使用 DiscardOldestPolicy:
import java.util.concurrent.*;
public class DiscardOldestPolicyExample {
    public static void main(String[] args) {
        BlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(2);
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
            2, 4, 10L, TimeUnit.SECONDS, queue,
            new ThreadPoolExecutor.DiscardOldestPolicy() // 使用 DiscardOldestPolicy
        );
        for (int i = 0; i < 10; i++) {
            final int taskNumber = i + 1;
            executor.submit(() -> {
                System.out.println("Executing task " + taskNumber);
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            });
        }
        executor.shutdown();
    }
}來點(diǎn)通俗易懂的
為了更好地理解這些拒絕策略,我們可以將其類比于生活中的場(chǎng)景:
- AbortPolicy:就像餐廳已滿員,不再接待新客人,并告知客人“已經(jīng)客滿,請(qǐng)去別處”。
 - CallerRunsPolicy:就像餐廳忙不過來時(shí),老板自己上陣服務(wù)客人,保證所有客人都能被服務(wù)到。
 - DiscardPolicy:就像餐廳已滿員,直接不理會(huì)新來的客人,不告知任何信息。
 - DiscardOldestPolicy:就像餐廳已滿員,把最早來但還沒點(diǎn)菜的客人請(qǐng)走,以便接待新來的客人。
 
自定義拒絕策略
除了內(nèi)置的拒絕策略,開發(fā)者還可以根據(jù)實(shí)際需求自定義拒絕策略。例如,記錄日志、發(fā)送通知等。
import java.util.concurrent.*;
public class CustomRejectionPolicyExample {
    public static void main(String[] args) {
        BlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(2);
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
            2, 4, 10L, TimeUnit.SECONDS, queue,
            new RejectedExecutionHandler() {
                @Override
                public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                    System.err.println("Task " + r.toString() + " was rejected");
                    // 這里可以添加更多處理邏輯,比如記錄日志、發(fā)送通知等
                }
            }
        );
        for (int i = 0; i < 10; i++) {
            final int taskNumber = i + 1;
            executor.submit(() -> {
                System.out.println("Executing task " + taskNumber);
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            });
        }
        executor.shutdown();
    }
}結(jié)語
通過本文的介紹和代碼示例,相信大家對(duì) Java 線程池的拒絕策略有了更深入的理解。在實(shí)際開發(fā)中,選擇合適的拒絕策略能有效提升系統(tǒng)的穩(wěn)定性和用戶體驗(yàn)。















 
 
 
















 
 
 
 