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

  

posted @ 2022-05-14 16:10  bg_不够  阅读(161)  评论(0编辑  收藏  举报