线程池源码解读——回归基础

原创
2020/04/06 22:39
阅读数 476

线程池源码解读——回归基础

线程池源码解读——回归基础 

线程池的好处: JDK提供的创建线程池: java 中创建线程的方式: 线程池源码解读: 记录的知识点:

线程池的好处:

  1. 降低资源的开销

  2. 提高响应速度

  3. 提高线程的可管理性

JDK提供的创建线程池:

  1. Executors.newCachedThreadPool():能够灵活回收线程,存在OOM的风险。

  2. Executors.newFixedThreadPool(5) :能控制并发,不能灵活回收线程。

  3. Executors.newScheduThreadPool(5):能够定时按周期执行任务,不能灵活回收线程。

  4. Executors.newSingleThreadExecutor():能保证任务按顺序执行,性能不好。

java 中创建线程的方式:

创建只有一种:new Thread,其他只是任务。

线程池源码解读:

  • 自定义线程池:

public ThreadPoolExecutor(int corePoolSize, 核心线程数
                          int maximumPoolSize,最大线程数
                          long keepAliveTime,存活时间
                          TimeUnit unit,存活时间单位
                          BlockingQueue<Runnable> workQueue,任务队列
                          ThreadFactory threadFactory,线程工厂
                          RejectedExecutionHandler handler) 拒绝策略
  • 线程状态:

private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
private static final int COUNT_BITS = Integer.SIZE - 3;
private static final int CAPACITY   = (1 << COUNT_BITS) - 1;

// runState is stored in the high-order bits
private static final int RUNNING    = -1 << COUNT_BITS;
private static final int SHUTDOWN   =  0 << COUNT_BITS;
private static final int STOP       =  1 << COUNT_BITS;
private static final int TIDYING    =  2 << COUNT_BITS;
private static final int TERMINATED =  3 << COUNT_BITS;

// Packing and unpacking ctl
private static int runStateOf(int c)     { return c & ~CAPACITY; }
private static int workerCountOf(int c)  { return c & CAPACITY; }
private static int ctlOf(int rs, int wc) { return rs | wc; }
  • 线程池源码原理:

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

    核心方法:addWorker

    private boolean addWorker(Runnable firstTask, boolean core) {
        // 标记
        retry:
        ...
        // 与最大线程池做比较
        wc >= (core ? corePoolSize : maximumPoolSize))
              return false;
        if (compareAndIncrementWorkerCount(c))
              break retry;
        ...
        boolean workerStarted = false;
        boolean workerAdded = false;
        Worker w = null;
        ...
        w = new Worker(firstTask);
        final Thread t = w.thread;
        // 重入锁控制线程安全
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        if (workerAdded) {
            t.start();
            workerStarted = true;
        }
        mainLock.unlock();
        ...
        return workerStarted;
    }
  • 线程池源码原理图:

记录的知识点:

  • 线程池流程顺序:核心线程池执行任务,任务加入队列、最大线程池处理任务,拒绝策略。

  • 线程池中使用了队列,ReentrantLock

  • 线程池源码中else代码没有(代码风格可学习)

  • 线程池主要应用场景为优化。提升响应时间。

  • Fork/Join 并行执行任务

  • 美团技术相关线程池学习-推荐


从基础 到 框架 再到 基础。保持危机感。

展开阅读全文
加载中

作者的其它热门文章

打赏
0
0 收藏
分享
打赏
1 评论
0 收藏
0
分享
返回顶部
顶部