ExecutorService
工具类
public class ThreadUtil
{
private static final Logger logger = LoggerFactory.getLogger(Threads.class);
/**
* sleep等待,单位为毫秒
*/
public static void sleep(long milliseconds)
{
try
{
Thread.sleep(milliseconds);
}
catch (InterruptedException e)
{
return;
}
}
/**
* 停止线程池
* 先使用shutdown, 停止接收新任务并尝试完成所有已存在任务.
* 如果超时, 则调用shutdownNow, 取消在workQueue中Pending的任务,并中断所有阻塞函数.
* 如果仍然超時,則強制退出.
* 另对在shutdown时线程本身被调用中断做了处理.
*/
public static void shutdownAndAwaitTermination(ExecutorService pool)
{
if (pool != null && !pool.isShutdown())
{
pool.shutdown();// 禁止提交新任务
try
{// 等待现有任务完成
if (!pool.awaitTermination(120, TimeUnit.SECONDS))
{
pool.shutdownNow();// 尝试取消正在执行的任务
if (!pool.awaitTermination(120, TimeUnit.SECONDS))
{
logger.info("Pool did not terminate");
}
}
}
catch (InterruptedException ie)
{
pool.shutdownNow();
Thread.currentThread().interrupt();
}
}
}
/**
* 打印线程异常信息
*/
public static void printException(Runnable r, Throwable t)
{
if (t == null && r instanceof Future<?>)
{
try
{
Future<?> future = (Future<?>) r;
if (future.isDone())
{
future.get();
}
}
catch (CancellationException ce)
{
t = ce;
}
catch (ExecutionException ee)
{
t = ee.getCause();
}
catch (InterruptedException ie)
{
Thread.currentThread().interrupt();
}
}
if (t != null)
{
logger.error(t.getMessage(), t);
}
}
}
优雅关停线程池
shutdownAndAwaitTermination
- shutdown
开始有序关闭线程池,与此同时,已提交的任务将继续执行,但不再接收新的任务,如果线程池已关闭,此方法调用不会产生额外影响。此方法不会等待已提交的任务执行完毕,要等待已提交任务执行完毕可以使用 awaitTermination() 方法。(不会等任务执行完毕的意思是这个方法不会阻塞,也就是说任务队列的任务会继续执行,但是其他的线程可能会抢在这些任务之前执行,而awaitTermination()方法可以实现阻塞并等待任务执行完毕)
- shutdownNow
当调用shutdownNow()时,线程池会立即停止接受新任务,尝试中断所有正在执行的任务,并返回那些尚未开始执行的任务。这通常用于必须立即停止所有活动任务的情况。
- awaitTermination
awaitTermination方法用于等待线程池终止,它在shutdown()或shutdownNow()方法被调用之后使用,用于等待所有任务完成执行或超时。该方法返回一个布尔值,指明在超时时间到达之前线程池是否已经完全终止。
捕获打印线程异常堆栈信息
printException
- submit
如果任务执行失败或取消了才会抛出异常,且如果在调用者线程使用get时没有捕获异常,一旦出现异常调用者线程将会因异常抛出而被中断
- execute
execute在任务执行时,如果出现异常,默认在执行线程中会抛出异常并打印堆栈信息,且会删除执行的线程,本次execute要执行的任务就视为结束了,异常的抛出不会中断调用者线程;
如果提交的任务很多,且抛出了异常的话线程池将会不断地创建线程 销毁线程