线程池的拒绝策略用于在提交的任务队列已满时决定如何拒绝新的任务。以下是几种常见的线程池拒绝策略:
-
CallerRunsPolicy:当任务被拒绝时,由提交任务的线程来执行该任务。这样可以降低新任务的提交速度,但是可能会影响到调用线程的性能。
-
AbortPolicy:当任务被拒绝时,直接抛出RejectedExecutionException异常。这是线程池默认的拒绝策略。使用此策略时,如果线程池无法处理新的任务,它将快速失败并抛出异常。
-
DiscardPolicy:当任务被拒绝时,直接丢弃该任务,不会有任何异常抛出。
-
DiscardOldestPolicy:当任务被拒绝时,丢弃队列中最老的一个任务,并尝试再次提交被拒绝的任务。
可以根据实际需求选择适合的拒绝策略。如果需要更精细的控制,还可以实现RejectedExecutionHandler接口来自定义拒绝策略。
代码演示:
1.CallerRunsPolicy
package com.blb.demo;
import java.util.concurrent.*;
public class Demo {
public static void main(String[] args) {
// 创建线程池,设置核心线程数为2,最大线程数为4,使用有界队列
ThreadPoolExecutor executor = new ThreadPoolExecutor(
2,
4,
0L,
TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>(3)
);
// 设置拒绝策略为CallerRunsPolicy
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// 提交10个任务给线程池
for (int i = 1; i <= 10; i++) {
final int taskId = i;
executor.submit(new Runnable() {
public void run() {
System.out.println("Task " + taskId + " is running on thread " + Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
// 关闭线程池
executor.shutdown();
}
}
以上代码创建了一个线程池,设置了核心线程数为2,最大线程数为4,并使用了无界队列。拒绝策略被设置为CallerRunsPolicy,即当任务被拒绝时,由提交任务的线程来执行该任务。最后提交了10个任务给线程池,并输出每个任务的执行线程名字。
你可以根据需要修改线程池的参数和拒绝策略来满足具体的需求。
2.AbortPolicy
package com.blb.demo;
import java.util.concurrent.*;
public class Demo {
public static void main(String[] args) {
// 创建线程池,设置核心线程数为2,最大线程数为4,使用有界队列
ThreadPoolExecutor executor = new ThreadPoolExecutor(
2,
4,
0L,
TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>(3)
);
// 设置拒绝策略为AbortPolicy
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
// 提交10个任务给线程池
for (int i = 1; i <= 10; i++) {
final int taskId = i;
executor.submit(new Runnable() {
public void run() {
System.out.println("Task " + taskId + " is running on thread " + Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
// 关闭线程池
executor.shutdown();
}
}
以上代码创建了一个线程池,设置了核心线程数为2,最大线程数为4,并使用了无界队列。拒绝策略被设置为AbortPolicy
,即当任务被拒绝时,直接抛出RejectedExecutionException
异常。最后提交了10个任务给线程池,并输出每个任务的执行线程名字。
请注意,使用AbortPolicy
拒绝策略会在任务被拒绝时抛出异常,因此需要适当处理异常情况。
3.DiscardPolicy
package com.blb.demo;
import java.util.concurrent.*;
public class Demo {
public static void main(String[] args) {
// 创建线程池,设置核心线程数为2,最大线程数为4,使用无界队列
ThreadPoolExecutor executor = new ThreadPoolExecutor(
2,
4,
0L,
TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>(3)
);
// 设置拒绝策略为DiscardPolicy
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());
// 提交10个任务给线程池
for (int i = 1; i <= 10; i++) {
final int taskId = i;
executor.submit(new Runnable() {
public void run() {
System.out.println("Task " + taskId + " is running on thread " + Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
// 关闭线程池
executor.shutdown();
}
}
在这个示例中,我们创建了一个线程池并设置核心线程数为2,最大线程数为4,使用有界队列(大小为3)。然后,我们将拒绝策略设置为DiscardPolicy
,这意味着当线程池无法处理新的任务时,会默默地丢弃被拒绝的任务,不抛出任何异常。
在提交了10个任务后,由于线程池中的线程数量有限,无法同时执行所有任务。所以,当队列已满时,DiscardPolicy
会直接丢弃被拒绝的任务。
请记住,使用DiscardPolicy
拒绝策略可能会导致无法执行的任务被丢弃,而不会得到执行。因此,要谨慎选择拒绝策略,确保符合你的业务需求。
4.DiscardOldestPolicy
package com.blb.demo;
import java.util.concurrent.*;
public class Demo {
public static void main(String[] args) {
// 创建线程池,设置核心线程数为2,最大线程数为4,使用有界队列
ThreadPoolExecutor executor = new ThreadPoolExecutor(
2,
4,
0L,
TimeUnit.MILLISECONDS,
new ArrayBlockingQueue<>(3)
);
// 设置拒绝策略为DiscardOldestPolicy
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardOldestPolicy());
// 提交10个任务给线程池
for (int i = 1; i <= 10; i++) {
final int taskId = i;
executor.submit(new Runnable() {
public void run() {
System.out.println("Task " + taskId + " is running on thread " + Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
// 关闭线程池
executor.shutdown();
}
}
在这个示例中,我们创建了一个线程池,并设置核心线程数为2,最大线程数为4,使用有界队列(大小为3)。然后,我们将拒绝策略设置为DiscardOldestPolicy
,这意味着当线程池无法处理新的任务时,会丢弃队列中的最早的任务,并尝试将新的任务添加到队列中。
在提交了10个任务后,由于线程池中的线程数量有限,无法同时执行所有任务。当队列已满且线程池已达到最大线程数时,DiscardOldestPolicy
会丢弃队列中最早的任务(即排在队列前面的任务),然后尝试将新的任务添加到队列中。
请注意,使用DiscardOldestPolicy
拒绝策略可能会导致一些任务被丢弃,而不会得到执行。因此,确保选择适合你业务需求的拒绝策略。
以上就是线程池的四种拒绝策略。