java中使用线程池一般使用Executors的工厂方法配置,newCachedThreadPool()创建无界线程池,可以进行线程的自动回收,newFixedThreadPool(int)创建固定大小的线程池,newSingleThreadExecutor()创建单线程线程池,它们通过对构造函数传递不同的参数来配置不同类型的线程池。
线程池构造函数:ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime,TimeUnit unit, BlockingQueue<Runnable> workQueue)
corePoolSize为核心线程的数量,maximumPoolSize为最大线程数量。当线程数量少于corePoolSize,则创建新线程,当线程数量大于corePoolSize,少于maximumPoolSize则把任务投入任务队列,如果任务队列满则创建新线程,如果线程数量达到最大值并且任务队列满则拒绝任务。
keepAliveTime表示线程保持活动的时间,unit为时间的单位。当线程空闲时间超过keepAliveTime就会终止。
workQueue为任务队列,主线程向任务队列中提交任务,子线程从任务队列中获取并执行任务。可配置为直接提交队列
SynchronousQueue,无界队列
newCachedThreadPool()等价于new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()),所有的任务直接提交,如果没有空闲线程则创建新线程,线程空闲时间超过60秒则会终止线程。LinkedBlockingQueue,有界队列
ArrayBlockingQueue。
newFixedThreadPool(nThreads)等价于new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()),当线程数量小于nThreads则创建线程,线程数量达到nThreads所有提交的任务都会放入无界任务队列
newSingleThreadExecutor()等价于new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())
当向线程池中提交任务时,线程池会根据当前线程的数量来决定是创建新线程还是提交给任务队列
1.当线程数量少于corePoolSize,则调用addIfUnderCorePoolSize()创建新线程
2.当线程数量大于corePoolSize,少于maximumPoolSize则把任务投入任务队列
3.如果任务队列满,则调用addIfUnderMaximumPoolSiz创建新线程
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);//当线程池shutdown 或者是CacheThreadPool中第一个核心线程执行
}
//阻塞队列是直接提交队列或者是有界队列达到界限,放入失败。继续创建线程
else if (!addIfUnderMaximumPoolSize(command))
reject(command); // is shutdown or saturated//线程数量超过最大线程数或者创建新线程失败
}
}
addIfUnderCorePoolSize()判断当前线程数量是否小于核心线程数量,通过调用addThread()创建新线程
private boolean addIfUnderCorePoolSize(Runnable firstTask) {
Thread t = null;
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
if (poolSize < corePoolSize && runState == RUNNING)//线程数量小于核心线程数量,开启新线程
t = addThread(firstTask);
} finally {
mainLock.unlock();
}
if (t == null)
return false;
t.start();
return true;
}
addIfUnderMaximumPoolSize()也通过调用addThread()方法创建新线程
private boolean addIfUnderMaximumPoolSize(Runnable firstTask) {
Thread t = null;
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
if (poolSize < maximumPoolSize && runState == RUNNING)//线程数量小于最大线程数量,开启新线程
t = addThread(firstTask);
} finally {
mainLock.unlock();
}
if (t == null)
return false;
t.start();
return true;
}
addThread()方法比较简单,创建线程并加入并放入线程池的线程集合中
private Thread addThread(Runnable firstTask) {//创建新线程
Worker w = new Worker(firstTask);
Thread t = threadFactory.newThread(w);
if (t != null) {
w.thread = t;
workers.add(w);
int nt = ++poolSize;
if (nt > largestPoolSize)
largestPoolSize = nt;
}
return t;
}
Worker子线程则一直循环执行任务队列中的任务,如果获取任务则调用runTask()运行任务,否则workerDone()终止线程
public void run() {
try {
Runnable task = firstTask;
firstTask = null;
while (task != null || (task = getTask()) != null) {//循环地从阻塞队列中获取任务
runTask(task);//运行任务
task = null;
}
} finally {//返回null,终止线程
workerDone(this);
}
}
任务通过getTask()方法从任务队列中获得
1.当线程池shutdown,子线程会无阻塞获取任务,当任务被执行完成则会终止线程
2.对于配置了活动时间的cachedThreadPool,有限时间阻塞等待任务,如果超时则终止线程
3.没有配超时时间的固定大小线程池,则一直阻塞等待任务
Runnable getTask() {
for (;;) {
try {
int state = runState;
if (state > SHUTDOWN)
return null;
Runnable r;
if (state == SHUTDOWN) // Help drain queue
r = workQueue.poll();//线程池shutdown,无阻塞获取任务直至返回null
else if (poolSize > corePoolSize || allowCoreThreadTimeOut)
r = workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS);//有限时间等待,用于CachedTreadPool
else
r = workQueue.take();//阻塞获取任务
if (r != null)
return r;
if (workerCanExit()) {
if (runState >= SHUTDOWN) // Wake up others
interruptIdleWorkers();
return null;
}
// Else retry
} catch (InterruptedException ie) {
// On interruption, re-check runState
}
}
}
runTask()则会调用任务的run()方法执行任务
private void runTask(Runnable task) {
final ReentrantLock runLock = this.runLock;
runLock.lock();
try {
if (runState < STOP &&
Thread.interrupted() &&
runState >= STOP)
thread.interrupt();
boolean ran = false;
beforeExecute(thread, task);
try {
task.run();//执行任务
ran = true;
afterExecute(task, null);
++completedTasks;
} catch (RuntimeException ex) {
if (!ran)
afterExecute(task, ex);
throw ex;
}
} finally {
runLock.unlock();
}
}
在线程完成之前会调用workerDone()做一些处理
void workerDone(Worker w) {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
completedTaskCount += w.completedTasks;
workers.remove(w);//从线程集合中删除
if (--poolSize == 0)//线程数量减1
tryTerminate();//尝试终止线程池
} finally {
mainLock.unlock();
}
}
最后是我写的一个线程池的简单实现,线程池主线程提交任务到任务队列,子线程通过从任务队列提取并执行任务,没有实现超时回收线程功能
public class ThreadPool
{
private volatile int corePoolSize;//核心线程数量
private volatile int maxPoolSize;//最大线程数量
private volatile int poolSize;//当前线程数量
private final HashSet<Worker> workers = new HashSet<Worker>();//工作线程
private final BlockingQueue<Runnable> queue;//任务队列
//工厂方法,创建无界线程池
public static ThreadPool newCachedThreadPool()
{
return new ThreadPool(0, Integer.MAX_VALUE, new SynchronousQueue<Runnable>());
}
//固定大小线程池
public static ThreadPool newFixedThreadPool(int nThreads)
{
return new ThreadPool(nThreads, nThreads, new LinkedBlockingQueue<Runnable>());
}
//单线程
public static ThreadPool newSingleThreadExecutor()
{
return new ThreadPool(1, 1, new LinkedBlockingQueue<Runnable>());
}
//构造函数
public ThreadPool(int corePoolSize, int maxPoolSize, BlockingQueue<Runnable> queue)
{
this.corePoolSize = corePoolSize;
this.maxPoolSize = maxPoolSize;
this.queue = queue;
}
//提交任务
public void execute(Runnable task)
{
if(poolSize < corePoolSize)//线程数量小于核心线程数量,创建新线程
{
addThread(task);
}
else if(poolSize < maxPoolSize)//线程数量小于最大线程数量
{
if(poolSize == 0 || !queue.offer(task))//提交任务到任务队列
addThread(task);//任务队列已满或没有工作线程,创建新线程
}
else//线程达到最大线程数量
{
if(!queue.offer(task))//提交任务到任务队列
System.out.println("too many tasks and threads.");//提交失败
}
}
//终止线程池,关闭线程
public void shutDown()
{
for (Worker worker : workers)
{
worker.thread.interrupt();
}
}
//创建新线程
private void addThread(Runnable task)
{
Worker w = new Worker(task);
Thread t = new Thread(w);
w.thread = t;
workers.add(w);
poolSize++;
t.start();
}
//工作线程
class Worker implements Runnable
{
Runnable task;
Thread thread;
Worker(Runnable task)
{
this.task = task;
}
public void run()
{
//循环获取并执行任务
while(task != null || (task = getTask()) != null)
{
task.run();
task = null;
}
}
//获取任务,线程被中断则返回null,终止线程
private Runnable getTask()
{
try
{
return queue.take();
}
catch (InterruptedException e)
{
return null;
}
}
}
}