Android 学习线程池ThreadPoolExecutor
ThreadPoolExecutor构造方法
@Test
public void ThreadPoolTest() {
ExecutorService executor = new ThreadPoolExecutor(
//corePoolSize:核心线程数
3,
//maximumPoolSize:最大线程数
5,
//空闲线程最大闲置时间 keepAliveTime:时间的值, unit:时间的单位 例如秒
10L, TimeUnit.SECONDS,
//用于保存任务的队列,可以为无界、有界、同步移交三种队列类型之一,
// 当池子里的工作线程数大于corePoolSize时,这时新进来的任务会被放到队列中
//一共有3种:
//SynchronousQueue(同步移交队列):队列不作为任务的缓冲方式,可以简单理解为队列长度为零
//LinkedBlockingQueue(无界队列):队列长度不受限制,当请求越来越多时(任务处理速度跟不上任务提交速度造成请求堆积)
// 可能导致内存占用过多或OOM
//ArrayBlockintQueue(有界队列):队列长度受限,当队列满了就需要创建多余的线程来执行任务
new ArrayBlockingQueue<>(3),
//创建线程的工厂类,默认使用Executors.defaultThreadFactory(),也可以使用guava库的ThreadFactoryBuilder来创建
Executors.defaultThreadFactory(),
//拒绝策略:
//线程池无法继续接收任务(队列已满且线程数达到maximunPoolSize)时的饱和策略,
// 取值有
// AbortPolicy、中断抛出异常
// CallerRunsPolicy、默默丢弃任务,不进行任何通知
// DiscardOldestPolicy、丢弃掉在队列中存在时间最久的任务
// DiscardPolicy 让提交任务的线程去执行任务(对比前三种比较友好一丢丢)
new ThreadPoolExecutor.AbortPolicy()
);
System.out.println("开始执行线程里面的线程");
for (int i = 0; i < 6; i++) {
executor.execute(() -> {
System.out.println(Thread.currentThread().getName() + ":正在执行任务");
});
}
executor.shutdown();
System.out.println("线程执行结束");
}
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
Okhttp源码中关于线程池的使用 在Dispatcher里面
public synchronized ExecutorService executorService() {
if (executorService == null) {
//corePoolSize=0,maxPoolSize为很大的数,同步移交队列,也就是说不维护常驻线程(核心线程),
// 每次来请求直接创建新线程来处理任务,也不使用队列缓冲,会自动回收多余线程,
// 由于将maxPoolSize设置成Integer.MAX_VALUE,
// 当请求很多时就可能创建过多的线程,导致资源耗尽OOM
//这里可以调用Executors的方法达到同样的效果
// public static ExecutorService newCachedThreadPool() {
// return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
// 60L, TimeUnit.SECONDS,
// new SynchronousQueue<Runnable>());
// }
executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp Dispatcher", false));
}
return executorService;
}
Worker
ThreadPoolExecutor的execute()跳入进去发现会有一个新的类Worker。Worker维护了一个thread和一个Runnable,运行时调用ThreadPoolExecutor的runWorker()方法
private final class Worker
extends AbstractQueuedSynchronizer
implements Runnable {
final Thread thread;
Runnable firstTask;
//构造方法
Worker(Runnable firstTask) {
setState(-1); // inhibit interrupts until runWorker 在运行Worker之前禁止中断
this.firstTask = firstTask;
//获取创建线程的工厂产生一个线程
this.thread = getThreadFactory().newThread(this);
}
//将run方法交给ThreadPoolExecutor的runWorker调用
public void run() {
runWorker(this);
}
}
final void runWorker(Worker w) {
Thread wt = Thread.currentThread();
Runnable task = w.firstTask;//将Worker里面要执行的Runnable交给task
w.firstTask = null;
w.unlock(); // allow interrupts 先解锁Worker
try {
while (task != null || (task = getTask()) != null) {
w.lock();//给Worker加锁
// 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 (Throwable x) {
//...
} finally {
afterExecute(task, thrown);//执行结束之后调用
}
} finally {
task = null;
w.completedTasks++;
w.unlock();//解锁
}
}
}
}
ThreadPoolExecutor的executor()方法添加Worker
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
/*
* 有3种情况
* 1.运行线程数少于核心线程数,那么Worker就是一个firstTask
*
* 2.如果运行线程大于核心线程。就会判断是否有已经运行结束的线程,
* 如果有就拿来使用,如果没有就创建新线程
*
* 3. 如果排队的任务也就是BlockingQueue队列满了就会执行拒绝策略
*/
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);
}

浙公网安备 33010602011771号