1. ThreadFactory+executor+UncaughtExceptionHandle处理异常
对线程池的创建中可以使用自定义的ThreadFactory,使用自定义的ThreadFactory时如果出现异常完全可以自定义处理。
MyThreadFactory 自定义的线程工厂,包含自定义的异常处理
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.concurrent.ThreadFactory;
public class MyThreadFactory implements ThreadFactory{
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setName("定制线程池大小的自定义线程工厂 ");
thread.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println("自定义线程处理异常开始 "+ thread.getName());
e.printStackTrace();
}
});
return thread;
}
}
测试代码
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class MyThreadPoolExecutor {
public static void main(String[] args) throws InterruptedException {
ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 4, 5, TimeUnit.SECONDS,
new LinkedBlockingDeque<Runnable>(),new MyThreadFactory());
executor.execute(()->{
System.out.println(Thread.currentThread().getName()+" begin "+System.currentTimeMillis());
String s=null;
s.indexOf("a");
System.out.println(Thread.currentThread().getName()+" end "+System.currentTimeMillis());
});
}
}
测试结果:
定制线程池大小的自定义线程工厂 begin 1596344223105
自定义线程处理异常开始 定制线程池大小的自定义线程工厂
java.lang.NullPointerException
at thread.api.executor.MyThreadPoolExecutor.lambda0(MyThreadPoolExecutor.java:14)atjava.util.concurrent.ThreadPoolExecutor.runWorker(UnknownSource)atjava.util.concurrent.ThreadPoolExecutor0(MyThreadPoolExecutor.java:14)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor0(MyThreadPoolExecutor.java:14)atjava.util.concurrent.ThreadPoolExecutor.runWorker(UnknownSource)atjava.util.concurrent.ThreadPoolExecutorWorker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
2. setRejectedExecutionHandler
用于设置线程池的拒绝策略,也可以设置成我们自定义的拒绝策略,构造方法中也是可以设置的,传入的拒绝策略为NULL会抛出异常。
自定义的拒绝策略
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
public class MyRejectedExcutionHandler implements RejectedExecutionHandler{
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
System.out.println("自定义拒接策略被执行");
}
}
测试代码
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class MyThreadPoolExecutor {
public static void main(String[] args) throws InterruptedException {
ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 2, 5, TimeUnit.SECONDS,
new LinkedBlockingDeque<Runnable>(1),new MyThreadFactory());
executor.setRejectedExecutionHandler(new MyRejectedExcutionHandler());
for(int i = 0;i<4;i++) {
executor.execute(()->{
System.out.println(Thread.currentThread().getName()+" begin "+System.currentTimeMillis());
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+" end "+System.currentTimeMillis());
});
}
}
}
测试结果:
定制线程池大小的自定义线程工厂 begin 1596348608702
定制线程池大小的自定义线程工厂 begin 1596348608702
自定义拒接策略被执行
定制线程池大小的自定义线程工厂 end 1596348609703
定制线程池大小的自定义线程工厂 end 1596348609703
定制线程池大小的自定义线程工厂 begin 1596348609703
定制线程池大小的自定义线程工厂 end 1596348610703
3. prestartCoreThread 每次调用就会创建一个核心线程,返回是否启动成功
public boolean prestartCoreThread() {
return workerCountOf(ctl.get()) < corePoolSize &&
addWorker(null, true);
}
4. prestartAllCoreThreads 启动全部核心线程,返回启动核心线程数
public int prestartAllCoreThreads() {
int n = 0;
while (addWorker(null, true))
++n;
return n;
}
5. getCompletedTaskCount 取得已经执行完的任务数
public long getCompletedTaskCount() {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
long n = completedTaskCount;
for (Worker w : workers)
n += w.completedTasks;
return n;
} finally {
mainLock.unlock();
}
}
6. ThreadPoolExecutor的拒绝策略
- AbortPolicy :当任务添加到线程池中被拒绝时,抛出RejectedExcctionException异常,ThreadPoolExecutor默认的拒绝策略。
- CallerRunsPolicy:当任务添加到线程池中被拒绝时,会使用调用线程池的线程对象处理被拒绝的任务。
- DiscardOldestPolicy:当任务添加到线程池中被拒绝时,线程池会放弃等待队列中最久的未处理任务,然后将拒绝任务添加到队列中。
- DiscardPolicy:当任务添加到线程池中被拒绝时,线程池将丢弃被拒绝的任务。
7. beforeExecute和afterExecute
重写ThreadPoolExecutor的这两个方法可以对线程池中的对象进行监控,了解当前线程池中谁准备执行,谁执行完毕。
MyRunnable
import java.util.concurrent.TimeUnit;
public class MyRunnable implements Runnable{
private String uaseName;
public MyRunnable(String uaseName) {
super();
this.uaseName = uaseName;
}
public String getUaseName() {
return uaseName;
}
public void setUaseName(String uaseName) {
this.uaseName = uaseName;
}
@Override
public void run() {
System.out.println("线程 "+uaseName+" 开始执行");
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("线程 "+uaseName+" 执行完成");
}
}
MyThreadPoolExecutor
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class MyThreadPoolExecutor extends ThreadPoolExecutor {
public MyThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
// TODO Auto-generated constructor stub
}
@Override
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
System.out.println(((MyRunnable) r).getUaseName() +"执行完毕");
}
@Override
protected void beforeExecute(Thread t, Runnable r){
super.beforeExecute(t,r);
System.out.println(((MyRunnable) r).getUaseName() +"开始执行");
}
}
测试代码
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;
public class ThreadPoolExecutorTest {
public static void main(String[] args) {
MyThreadPoolExecutor my = new MyThreadPoolExecutor(2,2,5,TimeUnit.SECONDS,
new LinkedBlockingDeque<Runnable>());
my.execute(new MyRunnable("A1"));
my.execute(new MyRunnable("A2"));
my.execute(new MyRunnable("A3"));
}
}
测试结果:
A1开始执行
A2开始执行
线程 A2 开始执行
线程 A1 开始执行
线程 A2 执行完成
A2执行完毕
A3开始执行
线程 A3 开始执行
线程 A1 执行完成
A1执行完毕
线程 A3 执行完成
A3执行完毕
8. remove方法
可以删除尚未执行的Runnable任务,注意只能删除execute(Runnable)方式提交的任务,submit(Runnable)提交的是不能删除的。
9. 多个getXxx方法说明
1. getActiveCount 获得当前线程池中正在执行任务的线程数。
2. getPoolSize 获得当前线程池里面有多少个线程,包括执行任务的和休眠状态的线程。
3. getCompletedTaskCount 获取线程池中已经执行完的任务数。
4. getCorePoolSize 获取核心线程数,就是构造时传入的corePoolSize。
5. getMaximumPoolSize 获取最大线程数,就是构造时传入的maximumPoolSize。
6. getTaskCount 获取发给线程池的任务总数。
10. Runnable接口在 ThreadPoolExecutor队列中时顺序取出,但是执行的时候却是乱序的。
本文介绍了如何使用ThreadFactory和UncaughtExceptionHandle处理线程池异常,以及设置自定义的拒绝策略。通过实例展示了prestartCoreThread、prestartAllCoreThreads等方法的功能,并详细解释了ThreadPoolExecutor的几种拒绝策略,如AbortPolicy、CallerRunsPolicy等。同时,讨论了beforeExecute和afterExecute方法在监控线程池执行情况中的作用,并提及了remove方法的使用以及线程池相关属性的获取方法。

被折叠的 条评论
为什么被折叠?



