赞
踩
传统的创建线程方式 new Thread(new Runnable(){}).start();
殊不知这种创建线程有以下缺点:
SingleThreadPool、FixedThreadPool、CachedThreadPool、ScheduledThreadPool
建议通过new ThreadPoolExecutor()
方式手动创建线程池,使我们更加明确线程池的运行规则,规避资源耗尽的风险。同时JDK默认实现的线程池实现有以下缺点:
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
根据任务类型,IO密集型还是计算密集型
所有任务的调度都是由execute方法完成的,这部分完成的工作是:检查现在线程池的运行状态、运行线程数、运行策略,决定接下来执行的流程,是直接申请线程执行,或是缓冲到队列中执行,亦或是直接拒绝该任务。其执行过程如下:
工作线程通过getTask
不断的获取任务,如果获取到任务,那么直接执行当前任务,否则阻塞等待任务的到来,如果超过一定的时间(空闲时间),还没有获取到任务,则线程被销毁。
ThreadPoolExecutor的运行状态有5种,分别为:
其生命周期转换如下入所示:
线程池中是以生产者消费者模式,通过一个阻塞队列来实现的。阻塞队列缓存任务,工作线程从阻塞队列中获取任务。
阻塞队列(BlockingQueue)是一个支持两个附加操作的队列。这两个附加的操作是:在队列为空时,获取元素的线程会等待队列变为非空。当队列满时,存储元素的线程会等待队列可用。
任务拒绝模块是线程池的保护部分,线程池有一个最大的容量,当线程池的任务缓存队列已满,并且线程池中的线程数目达到maximumPoolSize时,就需要拒绝掉该任务,采取任务拒绝策略,保护线程池。
拒绝策略是一个接口,其设计如下:
public interface RejectedExecutionHandler {
void rejectedExecution(Runnable r, ThreadPoolExecutor executor);
}
用户可以通过实现这个接口去定制拒绝策略,也可以选择JDK提供的四种已有拒绝策略,其特点如下:
public void setCorePoolSize(int corePoolSize)
public void setMaximumPoolSize(int maximumPoolSize)
public void setKeepAliveTime(long time, TimeUnit unit)
public boolean prestartCoreThread()
预热一个核心线程public int prestartAllCoreThreads()
预热所有的核心线程public void allowCoreThreadTimeOut(boolean value)
线程发生未捕获的异常后,最终都会走到Thread#dispatchUncaughtException
方法
判断当前线程是否设置了UncaughtExceptionHandler
,设置了会回调它的uncaughtException
方法,否则回调线程组的uncaughtException
方法
// ThreadGroup.java public void uncaughtException(Thread t, Throwable e) { if (parent != null) { parent.uncaughtException(t, e); } else { // 这里判断是否设置了DefaultUncaughtExceptionHandler Thread.UncaughtExceptionHandler ueh = Thread.getDefaultUncaughtExceptionHandler(); if (ueh != null) { // 设置了,则回调uncaughtException()方法 ueh.uncaughtException(t, e); } else if (!(e instanceof ThreadDeath)) { // 没有设置,则打印日志输出 System.err.print("Exception in thread \"" + t.getName() + "\" "); e.printStackTrace(System.err); } } }
线程池对开发者提供了几组方法,我们可以监控到任务的执行状态。这些方法在 ThreadPoolExecutor.java
中
// 线程池中每个任务执行前,会调用此方法
protected void beforeExecute(Thread t, Runnable r) { }
// 线程池中每个任务执行前,会调用此方法
protected void afterExecute(Runnable r, Throwable t) { }
// 线程池终止了
protected void terminated() { }
// 引用ThreadPoolExecutor.java提供的例子 public class PausableThreadPoolExecutor extends ThreadPoolExecutor { private boolean isPaused; private ReentrantLock pauseLock = new ReentrantLock(); private Condition unpaused = pauseLock.newCondition(); public PausableThreadPoolExecutor(...) { super(...); } protected void beforeExecute(Thread t, Runnable r) { super.beforeExecute(t, r); pauseLock.lock(); try { while (isPaused) unpaused.await(); } catch (InterruptedException ie) { t.interrupt(); } finally { pauseLock.unlock(); } } public void pause() { pauseLock.lock(); try { isPaused = true; } finally { pauseLock.unlock(); } } public void resume() { pauseLock.lock(); try { isPaused = false; unpaused.signalAll(); } finally { pauseLock.unlock(); } } }}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。