关于前端:2周刷完100道前端优质面试真题wumi

41次阅读

共计 2607 个字符,预计需要花费 7 分钟才能阅读完成。

download:2 周刷完 100 道前端优质面试真题

备链:https://www.sisuoit.com/2566.html

线程池执行流程

想要真正的理解线程池的执行流程,就得先从线程池的执行办法 execute() 说起,execute() 实现源码如下:

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);
        // 如果线程池的线程数为 0 时(当 corePoolSize 设置为 0 时会产生)else if (workerCountOf(recheck) == 0)
            addWorker(null, false); // 新建线程执行工作
    }
    // 外围线程都在忙且队列都已爆满,尝试新启动一个线程执行失败
    else if (!addWorker(command, false)) 
        // 执行回绝策略
        reject(command);
}

从上述源码咱们能够看出,当工作来了之后,线程池的执行流程是:先判断以后线程数是否大于外围线程数?如果后果为 false,则新建线程并执行工作;如果后果为 true,则判断工作队列是否已满?如果后果为 false,则把工作增加到工作队列中期待线程执行,否则则判断以后线程数量是否超过最大线程数?如果后果为 false,则新建线程执行此工作,否则将执行线程池的回绝策略,

线程池回绝策略

当工作过多且线程池的工作队列已满时,此时就会执行线程池的回绝策略,线程池的回绝策略默认有以下 4 种:

  • AbortPolicy:停止策略,线程池会抛出异样并中止执行此工作;
  • CallerRunsPolicy:把工作交给增加此工作的(main)线程来执行;
  • DiscardPolicy:疏忽此工作,疏忽最新的一个工作;
  • DiscardOldestPolicy:疏忽最早的工作,最先退出队列的工作。
    默认的回绝策略为 AbortPolicy 停止策略。

DiscardPolicy 回绝策略

接下来咱们以 DiscardPolicy 疏忽此工作,疏忽最新的一个工作为例,演示一下回绝策略的具体应用,实现代码如下:

public static void main(String[] args) {
    // 工作的具体方法
    Runnable runnable = new Runnable() {
        @Override
        public void run() {System.out.println("当前任务被执行, 执行工夫:" + new Date() +
                               "执行线程:" + Thread.currentThread().getName());
            try {
                // 期待 1s
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {e.printStackTrace();
            }
        }
    };
    // 创立线程, 线程的工作队列的长度为 1
    ThreadPoolExecutor threadPool = new ThreadPoolExecutor(1, 1,
                                                           100, TimeUnit.SECONDS, new LinkedBlockingQueue<>(1),
                                                           new ThreadPoolExecutor.DiscardPolicy());
    // 增加并执行 4 个工作
    threadPool.execute(runnable);
    threadPool.execute(runnable);
    threadPool.execute(runnable);
    threadPool.execute(runnable);
    // 线程池执行完工作,敞开线程池
    threadPool.shutdown();}

以上程序的执行后果如下:

从上述执行后果能够看出,给线程池增加了 4 个工作,而线程池只执行了 2 个工作就完结了,其余两个工作执行了回绝策略 DiscardPolicy 被忽略了,这就是回绝策略的作用。

AbortPolicy 回绝策略

为了和 DiscardPolicy 回绝策略比照,咱们来演示一下 JDK 默认的回绝策略 AbortPolicy 停止策略,线程池会抛出异样并中止执行此工作,示例代码如下:

public static void main(String[] args) {
    // 工作的具体方法
    Runnable runnable = new Runnable() {
        @Override
        public void run() {System.out.println("当前任务被执行, 执行工夫:" + new Date() +
                               "执行线程:" + Thread.currentThread().getName());
            try {
                // 期待 1s
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {e.printStackTrace();
            }
        }
    };
    // 创立线程, 线程的工作队列的长度为 1
    ThreadPoolExecutor threadPool = new ThreadPoolExecutor(1, 1,
                                                           100, TimeUnit.SECONDS, new LinkedBlockingQueue<>(1),
                                                           new ThreadPoolExecutor.AbortPolicy()); // 显式指定回绝策略,也能够疏忽此设置,它为默认回绝策略
    // 增加并执行 4 个工作
    threadPool.execute(runnable);
    threadPool.execute(runnable);
    threadPool.execute(runnable);
    threadPool.execute(runnable);
    // 线程池执行完工作,敞开线程池 

正文完
 0