<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">刚刚研究了一下java的线程池,写个随笔防治以后忘记</span>
<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">ThreadPoolExecutor是java中实现的线程池类。感觉更像是对许多线程进行管理的一个类。为什么要使用线程池呢?最主要的优点是可以减少线程创建与回收时消耗的资源。当需要使用使用线程的时候,我们会先创建一个Thread实例,通过Thread.start()来执行线程,在这个阶段中jvm会执行一系列的操作,当线程执行结束后jvm会将这些资源回收掉。当创建的线程很多时不断的创建与回收对象是非常不好的,因此要使用线程池来进行管理。在线程池中有几个全局变量需要说明:corePoolSize代表工作线程个数,maximumPoolSize代表最大工作线程个数,workQueue代表缓冲队列。线程池中每个工作线程被抽象成一个worker,worker定义如下:</span>
<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"></span><pre name="code" class="java">private final class Worker
extends AbstractQueuedSynchronizer
implements Runnable
{
/**
* This class will never be serialized, but we provide a
* serialVersionUID to suppress a javac warning.
*/
private static final long serialVersionUID = 6138294804551838833L;
/** Thread this worker is running in. Null if factory fails. */
final Thread thread;
/** Initial task to run. Possibly null. */
Runnable firstTask;
/** Per-thread task counter */
volatile long completedTasks;
/**
* Creates with given first task and thread from ThreadFactory.
* @param firstTask the first task (null if none)
*/
Worker(Runnable firstTask) {
setState(-1); // inhibit interrupts until runWorker
this.firstTask = firstTask;
this.thread = getThreadFactory().newThread(this);
}
/** Delegates main run loop to outer runWorker */
public void run() {
runWorker(this);
}
<span style="white-space:pre"> </span>...
}
worker实现了runnable,当创建一个thread的时候是以自身作为一个runnable来实现的。而firstTask则指向真正的任务,thread是当前所处的线程,以方便做一些中断操作等。因此有多少个工作线程就有多少个worker,每个workder处在不同的线程中,当任务执行结束后worker仍然存在不进行回收,当想要执行新的runnable时将空闲worker的firstTask指向过去并调用firstTask.run(),这个runnable仍然是运行在worker的线程中的,这样就避免了thread创建与回收,也就是实现了预期的线程池的作用。
<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">当创建一个ThreadPoolExecutor对象之后通过调用execute(Runnable r)方法来将一个runnable加入到线程池中</span>
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
int c = ctl.get();
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
if (! isRunning(recheck) && remove(command))
reject(command);
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
else if (!addWorker(command, false))
reject(command);
}
执行策略分为3步:
1.当前工作线程个数少于corePoolSize时创建一个新的线程并执行。
2.尝试将runnable加入到等待队列中。如果成功,进行一些必要的检查,检查失败则调用reject
3.如果当前工作线程小于maximumPoolSize,则尝试创建新的线程并执行,否则调用reject
每个worker开始执行后会调用runWorker方法
final void runWorker(Worker w) {
Thread wt = Thread.currentThread();
Runnable task = w.firstTask;
w.firstTask = null;
w.unlock(); // allow interrupts
boolean completedAbruptly = true;
try {
while (task != null || (task = getTask()) != null) {
w.lock();
// If pool is stopping, ensure thread is interrupted;
// if not, ensure thread is not interrupted. This
// requires a recheck in second case to deal with
// shutdownNow race while clearing interrupt
if ((runStateAtLeast(ctl.get(), STOP) ||
(Thread.interrupted() &&
runStateAtLeast(ctl.get(), STOP))) &&
!wt.isInterrupted())
wt.interrupt();
try {
beforeExecute(wt, task);
Throwable thrown = null;
try {
task.run();
} catch (RuntimeException x) {
thrown = x; throw x;
} catch (Error x) {
thrown = x; throw x;
} catch (Throwable x) {
thrown = x; throw new Error(x);
} finally {
afterExecute(task, thrown);
}
} finally {
task = null;
w.completedTasks++;
w.unlock();
}
}
completedAbruptly = false;
} finally {
processWorkerExit(w, completedAbruptly);
}
}
worker不断从缓冲队列中取出并执行,在调用getTask()取任务的时候有这样两句
Runnable r = timed ?
workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
workQueue.take();
通过workQueue的poll属性来实现线程池对worker存活时间的管理,不同的workerQueue结果也不一样。