今天看了线程池的拒绝策略:
我们看下ThreadPoolExecutor的API:看它的构造方法:
最后一个参数就是今天的主角:拒绝策略
首先点开这个类
我们发现他是一个接口,点开它的实现类,我们发现这些实现类就是我们所说的各种任务拒绝策略
我们一个一个分析
首先我们发现构造方法里有不需要拒绝策略的构造方法。那么一定就有一个默认的构造方法我们从这个讲起:
这就是我们的默认拒绝策略:它的拒绝方式是直接抛出异常。简单粗暴
试验:
我们自定义一个线程池:核心线程池大小为1,最大线程池大小为1,设置保留线程的时间为0,使用SynchronousQueue队列实现(这个队列是缓冲线程池中的队列,我们只需要知道在这里它拒绝接受线程就好了)
源码:
思路:当我们接受一个线程让他沉睡数秒,此时另一个线程进来,我们看看会发生什么
代码如下:
import java.util.concurrent.*;
class Thread1 extends Thread {
public void run() {
try {
Thread.sleep(1000);//线程1沉睡数秒,保证线程2进入线程池时,线程1还在运行中
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程" + Thread.currentThread().getName() + "输出:Threada");
}
}
class Thread2 extends Thread {
public void run() {
System.out.println("线程" + Thread.currentThread().getName() + "输出:Threadb");
}
}
public class Main {
public static void main(String[] args) throws InterruptedException {
Thread1 thread1 = new Thread1();
Thread2 thread2 = new Thread2();
ExecutorService executorService = new ThreadPoolExecutor(1, 1, 0,
TimeUnit.SECONDS, new SynchronousQueue<Runnable>());
executorService.execute(thread1);//执行线程1
executorService.execute(thread2);//线程1沉睡时线程2来了
executorService.shutdown();//关闭
}
}
执行结果:
抛出异常首先,然后1线程结束了沉睡完成输出
总结:这个拒绝策略就是当线程池满员,我们就直接抛出异常
2.再看一个![](https://i-blog.csdnimg.cn/blog_migrate/298fbe112c48e2ef9ad59bccb001ea9e.png)
这个拒绝策略也很简单,它的意思就是,假如现在使用到了拒绝策略,那么我就将这些被拒绝的线程用当前调用它们的线程执行这些任务
如:线程2被拒绝,是main线程调用这个线程开启的任务,因此我们直接去使用main的线程执行这些被拒绝的任务,如果执行线程池关闭了,那么就放弃这个任务
源码:
试验:
和上面的参数相同,只是改变了执行策略:代码如下:
import java.util.concurrent.*;
class Thread1 extends Thread {
public void run() {
try {
Thread.sleep(1000);//线程1沉睡数秒,保证线程2进入线程池时,线程1还在运行中
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程" + Thread.currentThread().getName() + "输出:Threada");
}
}
class Thread2 extends Thread {
public void run() {
System.out.println("线程" + Thread.currentThread().getName() + "输出:Threadb");
}
}
public class Main {
public static void main(String[] args) throws InterruptedException {
Thread1 thread1 = new Thread1();
Thread2 thread2 = new Thread2();
ExecutorService executorService= new ThreadPoolExecutor(1,1,0,
TimeUnit.SECONDS,new SynchronousQueue<Runnable>(),new
ThreadPoolExecutor.CallerRunsPolicy());
executorService.execute(thread1);//执行线程1
executorService.execute(thread2);//线程1沉睡时线程2来了
executorService.shutdown();//关闭
}
}
执行结果如下:
我们发现时用过了main线程执行了b任务,和上面说的一样
再看第三个:
当我们达到了执行拒绝策略的条件时,我们将任务队列中的最早的任务,也就是队列头移除,这时候再一次执行这个execute操作,这时没有其他因素影响的话我们就进了队列,等待执行了
源码:
测试如下:
我们设置三个线程,线程1先开启进入睡眠,然后线程2进入队列,此时再让线程3进来,我们的的预期结果是,把线程2踢出队列,线程3进入队列,线程1沉睡完后就执行线程3,线程2此时就被抛弃了:
import java.util.concurrent.*;
class Thread1 extends Thread {
public void run() {
try {
Thread.sleep(1000);//线程1沉睡数秒,保证线程2进入线程池时,线程1还在运行中
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程" + Thread.currentThread().getName() + "输出:Threada");
}
}
class Thread2 extends Thread {
public void run() {
System.out.println("线程" + Thread.currentThread().getName() + "输出:Threadb");
}
}
class Thread3 extends Thread {
public void run() {
System.out.println("线程" + Thread.currentThread().getName() + "输出:Threadc");
}
}
public class Main {
public static void main(String[] args) throws InterruptedException {
Thread1 thread1 = new Thread1();
Thread2 thread2 = new Thread2();
Thread3 thread3 = new Thread3();
ExecutorService executorService= new ThreadPoolExecutor(1,1,0,
TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(1),new ThreadPoolExecutor.DiscardOldestPolicy());
executorService.execute(thread1);//执行线程1
executorService.execute(thread2);//线程1沉睡时线程2来了,进入了工作队列等待
executorService.execute(thread3);//线程1沉睡时线程3来了,此时线程2位于队列中,队列满了,我们执行拒绝策略
executorService.shutdown();//关闭
}
}
执行结果:
先停顿了一下,然后输出上面的结果,我们发现并没有线程2执行
第四种:
这个很简单其实就是直接丢弃并且不抛出异常:
源码如下:
测试:
我们还是先让a进入后睡眠,此时b进来到了队列,c也进来,但是c该被拒绝通过拒绝策略,所以直接丢弃
代码如下:
import java.util.concurrent.*;
class Thread1 extends Thread {
public void run() {
try {
Thread.sleep(1000);//线程1沉睡数秒,保证线程2进入线程池时,线程1还在运行中
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程" + Thread.currentThread().getName() + "输出:Threada");
}
}
class Thread2 extends Thread {
public void run() {
System.out.println("线程" + Thread.currentThread().getName() + "输出:Threadb");
}
}
class Thread3 extends Thread {
public void run() {
System.out.println("线程" + Thread.currentThread().getName() + "输出:Threadc");
}
}
public class Main {
public static void main(String[] args) throws InterruptedException {
Thread1 thread1 = new Thread1();
Thread2 thread2 = new Thread2();
Thread3 thread3 = new Thread3();
ExecutorService executorService= new ThreadPoolExecutor(1,1,0,
TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(1),new ThreadPoolExecutor.DiscardPolicy());
executorService.execute(thread1);//执行线程1
executorService.execute(thread2);//线程1沉睡时线程2来了,进入了工作队列等待
executorService.execute(thread3);//线程1沉睡时线程3来了,此时线程2位于队列中,队列满了,我们执行拒绝策略,放弃线程3
executorService.shutdown();//关闭
}
}
执行结果如下:
只输出了a和b