线程池——张孝祥老师高新技术
线程池的概念与Excutors类的应用
创建固定大小的线程池
创建缓存线程池
创建单一线程池
关闭线程池
shutdown与shutdownNow的比较
用线程池启动定时器
调用ScheduledExecutorService的schedule方法,返回的ScheduleFuture对象可以取消任务。
支持间隔重复任务的定时方式,不直接支持绝对定时方式,需要转换成相对时间方式。
ThreadPoolExecutor是jdk1.5之后并发库中提供的线程池工具类。通过该类可以构造一个指定大小的线程池,通过BlockingQueue阻塞队列来实现工作任务线程执行控制。通过传入不同的Queue实现类,实现不同的阻塞控制。还可以通过不同的线程构造,设置线程构造方法。为了发挥线程池性能,必须良好配置corePoolSize、maxPoolSize、queue、和线程池满的状态下的拒绝策略。
execute方法
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
//如果任务个数大于当前任务池大小或创建任务线程失败
if (poolSize >= corePoolSize || !addIfUnderCorePoolSize(command)) {
//成功加入任务缓冲队列
if (runState == RUNNING && workQueue.offer(command)) {
if (runState != RUNNING || poolSize == 0)
ensureQueuedTaskHandled(command);
}
//否则判断是否大于最大线程数,并执行拒绝操作
else if (!addIfUnderMaximumPoolSize(command))
reject(command); // is shutdown or saturated
}
}
当任务线程数目小于corePoolSize时,创建新线程执行当前任务,否则加入queue中缓存。当任务线程数超过corePoolSize,判断是否小于maxPoolSize,是则创建新线程运行,否则进行拒绝处理。
Worker对象用来执行具体任务
run方法如下
public void run() {
try {
Runnable task = firstTask;
firstTask = null;
//执行任务,并在执行完成后,通过getTask()获取下一个任务
while (task != null || (task = getTask()) != null) {
runTask(task);
task = null;
}
} finally {
workerDone(this);
}
}
getTask()方法操作Queue缓冲队列获取新任务,如果当前任务线程数大于corePoolSize且无缓冲任务,则停止一个任务线程。如果任务线程数小于等于核心线程数但无缓冲任务,则阻塞当前任务线程。
Runnable getTask() {
for (;;) {
try {
int state = runState;
if (state > SHUTDOWN)
return null;
Runnable r;
if (state == SHUTDOWN) // Help drain queue
r = workQueue.poll();
//任务线程数超过核心池大小或允许一个超时时间等待新任务
else if (poolSize > corePoolSize || allowCoreThreadTimeOut)
//阻塞一个keepAliveTime时间
r = workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS);
else
r = workQueue.take(); //阻塞当前线程
if (r != null)
return r;
//任务缓冲池中没有任务,则允许停止一个任务线程,poolSize减少一个
if (workerCanExit()) {
if (runState >= SHUTDOWN) // Wake up others
interruptIdleWorkers();
return null;
}
// Else retry
} catch (InterruptedException ie) {
// On interruption, re-check runState
}
}
}
在后续的workDone中及时调整了线程池的工作线程数目。
线程池的概念与Excutors类的应用
创建固定大小的线程池
创建缓存线程池
创建单一线程池
关闭线程池
shutdown与shutdownNow的比较
用线程池启动定时器
调用ScheduledExecutorService的schedule方法,返回的ScheduleFuture对象可以取消任务。
支持间隔重复任务的定时方式,不直接支持绝对定时方式,需要转换成相对时间方式。
ThreadPoolExecutor是jdk1.5之后并发库中提供的线程池工具类。通过该类可以构造一个指定大小的线程池,通过BlockingQueue阻塞队列来实现工作任务线程执行控制。通过传入不同的Queue实现类,实现不同的阻塞控制。还可以通过不同的线程构造,设置线程构造方法。为了发挥线程池性能,必须良好配置corePoolSize、maxPoolSize、queue、和线程池满的状态下的拒绝策略。
execute方法
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
//如果任务个数大于当前任务池大小或创建任务线程失败
if (poolSize >= corePoolSize || !addIfUnderCorePoolSize(command)) {
//成功加入任务缓冲队列
if (runState == RUNNING && workQueue.offer(command)) {
if (runState != RUNNING || poolSize == 0)
ensureQueuedTaskHandled(command);
}
//否则判断是否大于最大线程数,并执行拒绝操作
else if (!addIfUnderMaximumPoolSize(command))
reject(command); // is shutdown or saturated
}
}
当任务线程数目小于corePoolSize时,创建新线程执行当前任务,否则加入queue中缓存。当任务线程数超过corePoolSize,判断是否小于maxPoolSize,是则创建新线程运行,否则进行拒绝处理。
Worker对象用来执行具体任务
run方法如下
public void run() {
try {
Runnable task = firstTask;
firstTask = null;
//执行任务,并在执行完成后,通过getTask()获取下一个任务
while (task != null || (task = getTask()) != null) {
runTask(task);
task = null;
}
} finally {
workerDone(this);
}
}
getTask()方法操作Queue缓冲队列获取新任务,如果当前任务线程数大于corePoolSize且无缓冲任务,则停止一个任务线程。如果任务线程数小于等于核心线程数但无缓冲任务,则阻塞当前任务线程。
Runnable getTask() {
for (;;) {
try {
int state = runState;
if (state > SHUTDOWN)
return null;
Runnable r;
if (state == SHUTDOWN) // Help drain queue
r = workQueue.poll();
//任务线程数超过核心池大小或允许一个超时时间等待新任务
else if (poolSize > corePoolSize || allowCoreThreadTimeOut)
//阻塞一个keepAliveTime时间
r = workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS);
else
r = workQueue.take(); //阻塞当前线程
if (r != null)
return r;
//任务缓冲池中没有任务,则允许停止一个任务线程,poolSize减少一个
if (workerCanExit()) {
if (runState >= SHUTDOWN) // Wake up others
interruptIdleWorkers();
return null;
}
// Else retry
} catch (InterruptedException ie) {
// On interruption, re-check runState
}
}
}
在后续的workDone中及时调整了线程池的工作线程数目。