公司的项目中使用了ExecutorService java中的线程池进行管理线程,使用submit进行线程申请线程时出现线程内抛出NullPointException被捕捉,导致调试难度急剧加大,原因是ExecutorService自行捕捉了异常,解决方法:
Future result = Executors.newCachedThreadPool().submit();
try {
result.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
throw new RuntimeException(e);
}
在这个地方将异常重新抛出。
这种方法虽然可以解决以上的问题,但get()是一个阻塞的方法,会一直等待结果。
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
System.out.print("++++++++++++++++++++++");
// e.printStackTrace();
}
});
ExecutorService executorService = Executors.newCachedThreadPool(new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
return t;
}
});
for (int i = 0; i < 10; i++) {
//这个地方如果使用sumbit则捕捉不到相关异常。
executorService.execute(new Runnable() {
@Override
public void run() {
// TODO: 2018/1/16 0016 线程任务
}
});
}
ExecutorService是java提供的线程管理工具,我们可以使用Executors来创建一个线程池,这样我们就不需要在使用线程的地方去new thread的了,现在java中创建线程池的方式有一下几种:
1.Executors.newCacheThreadPool();
CacheThreadBool会为每一个任务创造线程,会在程序执行过程中创建与所需线程相等的线程数,并在回收旧线程时停止创建旧线程。
2.Executors.newFixedThreadPool(size);
FixedThreadPool指定线程数量,在线程均被占用后排队等待空闲线程。
3.Executors.newSingleThreadExecutor();
相当于size = 1的FixedThreadPool,使用于独占式的操作,比如操作摄像头等硬件设备,不允许多线程同时占用。
使用线程池我们不需要care线程的启动以结束,但是我们要注意的是当池内消耗完之后的等待和同步问题,假设在测试期间并发测试很小的情况下,无法出现线程池内线程耗尽的情况,当某些糟糕的代码导致线程一直在使用的情况,就造成任务无法被及时处理甚至不处理。建议在测试阶段不要创建太大的池,方便及时发现代码漏洞。