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); }