线程池的4种拒绝策略
1、 中止策略
* 功能:当线程无法加入队列时,就会报异常,然后中止运行。
* 场景: ***
2、 调用者运行策略
* 功能:只要线程池没有关闭,就把任务给到当前线程处理先处理。
* 场景:一般在不允许失败的、对性能要求不高、并发量较小的场景下使用。 因为线程池一般情况下不会关闭,也就是提交的任务一定会被运行,但是由于是调用者线程自己执行的,当多次提交任务时,就会阻塞后续任务执行,性能和效率就会变慢。
3、 丢弃策略
* 功能:直接丢弃任务,不抛出任何错误或者异常
* 场景:如果你的任务无关紧要,那就可以用它。目前这个策略基本用不上了。
4.、弃老策略
* 功能:把最老的任务丢弃,新增新任务。
* 场景:和3一样
代码例子
import java.util.concurrent.*;
public class ThreadPoolArgumentsMain {
/**
* 1. 线程池的七大参数
* int corePoolSize 核心线程池大小
* int maximumPoolSize 最核心大线程池大小
* long keepAliveTime 超时时间 没有人使用会自动释放
* TimeUnit unit 超时单位
* BlockingQueue<Runnable> workQueue 阻塞队列
* ThreadFactory threadFactory 线程工厂,创建线程的,一般不用动
* RejectedExecutionHandler handler 拒绝策略
* 1. 抛出异常,中止任务 new ThreadPoolExecutor.AbortPolicy() 线程池默认拒绝策略,当添加到线程池失败就会抛出RejectedExecutionException异常
* 2. 使用调用线程执行任务 new ThreadPoolExecutor.CallerRunsPolicy() 如果添加失败,那么主线程会自己调用执行器中的execute方法来执行任务
* 3. 直接丢弃 new ThreadPoolExecutor.DiscardPolicy() 如果添加失败,则放弃,不会抛出异常
* 4. 丢弃队列最老任务,添加新任务 new ThreadPoolExecutor.DiscardOldestPolicy() 如果添加到线程池失败,会将队列中最古老添加的任务丢弃,再尝试添加,如果失败则按该策略不断重试
*/
public static void main(String[] args) {
// AbortPolicy();
// CallerRunsPolicy();
// DiscardPolicy();
// DiscardOldestPolicy();
}
/**
* 中止策略
* 功能:当线程无法加入队列时,就会报异常,然后中止运行。
* 场景: ***
*/
private static void AbortPolicy() {
int corePoolSize = 2;
int maximumPoolSize = 5;
long keepAliveTime = 10;
BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<Runnable>(8);
RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy();
ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.SECONDS, workQueue, handler);
for(int i=0; i< 15; i++) {
try {
int n = i + 1;
executor.execute(() -> {
try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); }
long num = 0;
for (long j = 1; j <= 2000000000 ; j++) {
num += j;
}
System.err.println("第" + n + "次使用名称叫" + Thread.currentThread().getName() + "线程,"+"最终入库的数是:"+num);
});
} catch (Exception e) {
e.printStackTrace();
}
}
executor.shutdown();
}
/**
* 调用者运行策略
* 功能:只要线程池没有关闭,就把任务给到当前线程处理先处理。
* 场景:一般在不允许失败的、对性能要求不高、并发量较小的场景下使用。
* 因为线程池一般情况下不会关闭,也就是提交的任务一定会被运行,但是由于是调用者线程自己执行的,当多次提交任务时,就会阻塞后续任务执行,性能和效率就会变慢。
*/
private static void CallerRunsPolicy() {
int corePoolSize = 2;
int maximumPoolSize = 5;
long keepAliveTime = 1;
BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<Runnable>(8);
RejectedExecutionHandler handler = new ThreadPoolExecutor.CallerRunsPolicy();
ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.SECONDS, workQueue, handler);
for(int i=0; i< 25; i++) {
try {
int n = i + 1;
executor.execute(() -> {
try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); }
long num = 0;
for (long j = 1; j <= 2000000000 ; j++) {
num += j;
}
System.err.println("第" + n + "次使用名称叫" + Thread.currentThread().getName() + "线程,"+"最终入库的数是:"+num);
});
} catch (Exception e) {
e.printStackTrace();
}
}
executor.shutdown();
}
/**
* 丢弃策略
* 功能:直接丢弃任务,不抛出任何错误或者异常
* 场景:如果你的任务无关紧要,那就可以用它。目前这个策略基本用不上了。
*/
private static void DiscardPolicy() {
int corePoolSize = 2;
int maximumPoolSize = 5;
long keepAliveTime = 1;
BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<Runnable>(8);
RejectedExecutionHandler handler = new ThreadPoolExecutor.DiscardPolicy();
ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.SECONDS, workQueue, handler);
for(int i=0; i< 20; i++) {
try {
int n = i + 1;
executor.execute(() -> {
try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); }
long num = 0;
for (long j = 1; j <= 2000000000 ; j++) {
num += j;
}
System.err.println("第" + n + "次使用名称叫" + Thread.currentThread().getName() + "线程,"+"最终入库的数是:"+num);
});
} catch (Exception e) {
e.printStackTrace();
}
}
executor.shutdown();
}
/**
* 弃老策略
* 功能:把最老的任务丢弃,新增新任务。
*
*/
private static void DiscardOldestPolicy() {
int corePoolSize = 2;
int maximumPoolSize = 5;
long keepAliveTime = 1;
BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<Runnable>(8);
RejectedExecutionHandler handler = new ThreadPoolExecutor.DiscardOldestPolicy();
ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.SECONDS, workQueue, handler);
for(int i=0; i< 25; i++) {
try {
int n = i + 1;
executor.execute(() -> {
try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); }
long num = 0;
for (long j = 1; j <= 2000000000 ; j++) {
num += j;
}
System.err.println("第" + n + "次使用名称叫" + Thread.currentThread().getName() + "线程,"+"最终入库的数是:"+num);
});
} catch (Exception e) {
e.printStackTrace();
}
}
executor.shutdown();
}
}
代码都给了!慢慢看吧。