线程池的设计和原理

线程使用上的问题 
new Thread().start();
   1. 线程的频繁创建好销毁
   2. 线程的数量过多,会造成CPU资源的开销。
1. 上下文切换 (消耗CPU资源)
思考: 如何实现线程的复用?
池化技术 
连接池、对象池、内存池、线程池 。。。
池化技术的核心: 复用
线程池 
提前创建一系列的线程,保存在这个线程池中。
有任务要执行的时候,从线程池中取出线程来执行。
没有任务的时候,线程池放回去。
Java中提供的线程池

Executors

newFixedThreadPool 固定线程数量

public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>());
}

newSingleThreadExecutor 只有一个线程的线程池
 

public static ExecutorService newSingleThreadExecutor() {
    return new FinalizableDelegatedExecutorService
       (new ThreadPoolExecutor(1, 1,
                                0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue<Runnable>()));
}

newCachedThreadPool 可以缓存的线程池 ->理论上来说,有多少请求,该线程池就可以创建多
少的线程来处理。

public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                  60L, TimeUnit.SECONDS,
                                  new SynchronousQueue<Runnable>());
}

newScheduledThreadPool //提供了按照周期执行的线程池. ->Timer

public static ScheduledExecutorService newScheduledThreadPool(int 
corePoolSize) {
    return new ScheduledThreadPoolExecutor(corePoolSize);
}

ThreadPoolExecutor

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.acc = System.getSecurityManager() == null ?
        null :
    AccessController.getContext();
    this.corePoolSize = corePoolSize;
    this.maximumPoolSize = maximumPoolSize;
    this.workQueue = workQueue;
    this.keepAliveTime = unit.toNanos(keepAliveTime);
    this.threadFactory = threadFactory;
    this.handler = handler;
}

线程池的设计思考

需求: 实现线程的重复使用.
分解:

如何线程的复用.
让线程实现复用的唯一的方法,就是让线程不结束。
那如何让线程执行新的任务呢?也就是说,任务怎么给他执行?
[共享内存]-> List.add()
线程一直处于运行状态,合理吗?
有任务来的时候,执行
没有任务的时候,阻塞
结论: 通过阻塞队列的方式,来实现线程池中线程的复用。
线程池的实现原理的过程推演

 源码分析

线程池中的核心线程是延迟初始化的。

1. 先初始化核心线程。
2. 调用阻塞队列的方法,把task存进去。(offer() -> true/false)
    1. 如果true ,说明当前的请求量不大, 核心线程就可以搞定。
    2. false,增加工作线程(非核心线程)
1. 如果添加失败,说明当前的工作线程数量达到了最大的线程数,直接调用拒绝策略。

public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
       
        int c = ctl.get();
        //判断当前工作线程数是否小于核心线程数(延迟初始化)
        if (workerCountOf(c) < corePoolSize) {
            if (addWorker(command, true)) //添加工作线程的同时,执行command
                return;
            c = ctl.get();
       }
        //workQueue.offer 添加到阻塞队列
        if (isRunning(c) && workQueue.offer(command)) {
addWorker 
            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:
    //case1 通过原子操作来增加线程数量.
    for (;;) {
        int c = ctl.get();
        int rs = runStateOf(c);
        // Check if queue empty only if necessary.
        if (rs >= SHUTDOWN &&
            ! (rs == SHUTDOWN &&
               firstTask == null &&
               ! workQueue.isEmpty()))
            return false;
        for (;;) {
            int wc = workerCountOf(c);
            if (wc >= CAPACITY ||
                wc >= (core ? corePoolSize : maximumPoolSize))
                return false;
            if (compareAndIncrementWorkerCount(c)) //通过原子操作来增加线程数量.
                break retry;
            c = ctl.get();  // Re-read ctl
            if (runStateOf(c) != rs)
                continue retry;
            // else CAS failed due to workerCount change; retry inner loop
       }
   }
    
    //case2 初始化工作线程.
    boolean workerStarted = false;
    boolean workerAdded = false;
    Worker w = null;
    try {
        //构建一个工作线程,此时还没有启动.
        w = new Worker(firstTask);
        final Thread t = w.thread;
        if (t != null) {
            final ReentrantLock mainLock = this.mainLock;
            mainLock.lock();
            try {
                // Recheck while holding lock.
                // Back out on ThreadFactory failure or if
                // shut down before lock acquired.
 
worker.run() 
 
                int rs = runStateOf(ctl.get());
                if (rs < SHUTDOWN ||
                   (rs == SHUTDOWN && firstTask == null)) {
                    if (t.isAlive()) // precheck that t is startable
                        throw new IllegalThreadStateException();
                    workers.add(w); //添加到一个容器中。
                    int s = workers.size();
                    if (s > largestPoolSize) //重新更新largestPoolSize
                        largestPoolSize = s;
                    workerAdded = true; //添加成功。
               }
           } finally {
                mainLock.unlock();
           }
            if (workerAdded) {
                t.start(); //启动线程
                workerStarted = true;
           }
       }
   } finally { //失败, 回滚。
        if (! workerStarted)
            addWorkerFailed(w);
   }
    return workerStarted;
}

worker.run()

public void run() {
    runWorker(this);
}
final void runWorker(Worker w) {
    Thread wt = Thread.currentThread();
    Runnable task = w.firstTask;
    w.firstTask = null;
    w.unlock(); // allow interrupts
    boolean completedAbruptly = true;
    try {
        //while循环保证当前线程不结束. 直到task为null
        while (task != null || (task = getTask()) != null) {
            //表示当前线程正在运行一个任务,如果其他地方要shutdown().你必须要等我执行完成。
            w.lock(); //Worker继承了AQS -> 实现了互斥锁
            // 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(); //执行task.run
               } catch (RuntimeException x) {
                    thrown = x; throw x;
               } catch (Error x) {
                    thrown = x; throw x;
               } catch (Throwable x) {
                    thrown = x; throw new Error(x);
               } finally {
                    afterExecute(task, thrown); //空的实现 ->
               }
           } finally {
                task = null;
                w.completedTasks++;
                w.unlock();
           }
       }
        completedAbruptly = false;
   } finally {
        processWorkerExit(w, completedAbruptly);
   }
}
private Runnable getTask() {
        boolean timedOut = false; // Did the last poll() time out?
        for (;;) { //cas 自旋
            int c = ctl.get();
            int rs = runStateOf(c);
 
            // 如果线程池已经结束状态,直接返回null. 需要清理掉所有的工作线程
            // Check if queue empty only if necessary.
            if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
                decrementWorkerCount();
                return null; //
           }
            int wc = workerCountOf(c);
 
            //是否允许超时
             // * allowCoreThreadTimeOut 为true 
             // * 如果当前的工作线程数量大于核心线程数
            // Are workers subject to culling?
            boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
 
            
            if ((wc > maximumPoolSize || (timed && timedOut))
                && (wc > 1 || workQueue.isEmpty())) {
                if (compareAndDecrementWorkerCount(c)) //cas 减少工作线程数量。 
                    return null; //表示要销毁当前工作线程.
                continue;
           }
 
            //获取任务的过程
            try {
                Runnable r = timed ?
                    workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
                    workQueue.take(); //如果阻塞队列没有任务,当前工作线程会阻塞在这里
                if (r != null)
                    return r;
                timedOut = true;
           } catch (InterruptedException retry) { //中断异常. 
                timedOut = false;
           }
       }
   }

线程数量设置

IO密集型 CPU 2core+1
CPU利用率不高
CPU密集型 CPU +1
CPU利用率很高,会增加上下文切换.

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值