1. 拒绝策略
超负荷了怎么办? 拒绝策略
ThreadPoolExecutor最后一个参数指定了拒绝策略。
也就是当任务数量超过了系统实际承载能力时,该如何处理。
这个时候就要用到拒绝策略。
拒绝策略通常用于系统超负荷运行时,也就是线程池中的线程已经用完了,无法继续为新任务服务,同时,
等待队列中也已经满了,再也塞不下新任务了。
JDK内置了四种拒绝策略:
AbortPolicy
该策略会直接抛出异常,阻止系统正常工作。CallerRunsPolicy
只要线程池未关闭,该策略直接在调用者线程中,运行当前被丢弃的任务。
任务提交线程的性能有可能会急剧下降。DiscardOldestPolicy
该策略将丢弃最老的一个请求。DiscardPolicy
该策略默默地丢弃无法处理的任务。
MyTask.java
public class MyTask implements Runnable {
@Override
public void run() {
System.out.println(System.currentTimeMillis() + ":Thread ID:" + Thread.currentThread().getId());
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
RejectThreadPoolDemo.java
public class RejectThreadPoolDemo {
public static void main(String[] args) throws InterruptedException {
MyTask task = new MyTask();
ExecutorService es = new ThreadPoolExecutor(5, 5, 0L, TimeUnit.MILLISECONDS,
new LinkedBlockingDeque<Runnable>(10),
Executors.defaultThreadFactory(),
new RejectedExecutionHandler() {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
System.out.println(r.toString() + " is discarded");
}
});
for (int i=0;i<Integer.MAX_VALUE;i++) {
es.submit(task);
Thread.sleep(10);
}
}
}
上述代码定义了一个有5个常驻线程,并且最大线程数也是5个的线程池。
这个线程池拥有一个10个容量的等待队列。
而且,自定义了拒绝策略,将丢弃的任务信息进行打印。
2. 自定义线程创建(ThreadFactory)
线程池中的线程从哪里来?
线程池是为了线程复用,避免线程的频繁创建。
那么,最开始的那些线程从哪里来?
答案是:
ThreadFactory(线程工厂)
ThreadFactory是一个接口,它只有一个方法newThread(Runnable r),用来创建线程。
因此,我们需要实现它来自定义自己的线程工厂。
通过自定义线程工厂来自定义线程创建有很多优势:
- 跟踪线程池创建了多少线程
- 自定义线程的名称,组以及优先级等信息
- 将所有线程设置为守护线程
示例代码:
public class MyTask implements Runnable {
@Override
public void run() {
System.out.println(System.currentTimeMillis() + ":Thread ID:" + Thread.currentThread().getId() + " Start...");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(System.currentTimeMillis() + ":Thread ID:" + Thread.currentThread().getId() + " End!");
}
}
public class CustomThreadFactoryDemo1 {
public static void main(String[] args) {
int threadNum = 5;
MyTask task = new MyTask();
// 自定义线程工厂
ExecutorService es = new ThreadPoolExecutor(5, 5, 0L, TimeUnit.MILLISECONDS,
new SynchronousQueue<>(),
new ThreadFactory() {
@Override
public Thread newThread(@NotNull Runnable r) {
Thread t = new Thread(r);
t.setDaemon(true);
System.out.println("create " + t);
return t;
}
});
for (int i = 0; i < threadNum; i++) {
es.submit(task);
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
运行结果:
create Thread[Thread-0,5,main]
create Thread[Thread-1,5,main]
create Thread[Thread-2,5,main]
create Thread[Thread-3,5,main]
create Thread[Thread-4,5,main]
1594989090932:Thread ID:14 Start...
1594989090932:Thread ID:13 Start...
1594989090933:Thread ID:16 Start...
1594989090933:Thread ID:17 Start...
1594989090932:Thread ID:15 Start...
1594989091955:Thread ID:16 End!
1594989091955:Thread ID:13 End!
1594989091955:Thread ID:15 End!
1594989091955:Thread ID:17 End!
1594989091955:Thread ID:14 End!