java 线程池知识点梳理

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_18416057/article/details/82423802

   今天本来在看eureka的心跳机制的,过程中碰到一些线程池的知识点,之前可能没有很全面的对线程池这一块去了解过,对一些相关类之间的关系不是很了解。趁着这个机会,今天打算更深入的去了解这一块东西

   首先我用startUML工具画了一个图,给大家简单的展示一下线程池相关类的关联信息(因为好久没有用和这个工具了,有画的不好的地方,请不要见怪)

上图大致的展示了其关联关系,首先从头说起,下面是Executor的源码,是一个接口,定义了一个execute方法

package java.util.concurrent;

public interface Executor {
    void execute(Runnable var1);
}
ExecutorService接口在原先的executor接口的接触上增加了一些方法

之后就是AbstractExecutorService类,该类实现ExecutorService接口,是一个抽象类。

最关键的就是ThreadPoolExecutor,它继承刚才说的那个抽象类,而且最重要的事是它有很多构造函数,不同的构造函数会创建不同的线程池,这是它的一个很重要的核心点

下面是构造器几个参数(直接从源码中摘取的)

 /**
     * Creates a new {@code ThreadPoolExecutor} with the given initial
     * parameters and default thread factory and rejected execution handler.
     * It may be more convenient to use one of the {@link Executors} factory
     * methods instead of this general purpose constructor.
     *
     * @param corePoolSize the number of threads to keep in the pool, even
     *        if they are idle, unless {@code allowCoreThreadTimeOut} is set
     * @param maximumPoolSize the maximum number of threads to allow in the
     *        pool
     * @param keepAliveTime when the number of threads is greater than
     *        the core, this is the maximum time that excess idle threads
     *        will wait for new tasks before terminating.
     * @param unit the time unit for the {@code keepAliveTime} argument
     * @param workQueue the queue to use for holding tasks before they are
     *        executed.  This queue will hold only the {@code Runnable}
     *        tasks submitted by the {@code execute} method.
     * @throws IllegalArgumentException if one of the following holds:<br>
     *         {@code corePoolSize < 0}<br>
     *         {@code keepAliveTime < 0}<br>
     *         {@code maximumPoolSize <= 0}<br>
     *         {@code maximumPoolSize < corePoolSize}
     * @throws NullPointerException if {@code workQueue} is null
     */

解释:

参数名 作用
corePoolSize 核心线程池大小
maximumPoolSize 最大线程池大小
keepAliveTime 线程池中超过corePoolSize数目的空闲线程最大存活时间;可以allowCoreThreadTimeOut(true)使得核心线程有效时间
TimeUnit keepAliveTime时间单位
workQueue 阻塞任务队列
threadFactory 新建线程工厂
RejectedExecutionHandler 当提交任务数超过maxmumPoolSize+workQueue之和时,任务会交给RejectedExecutionHandler来处理

然后我们先来看一下另一个类Executors,其实这个类就是一个拥有很多静态方法,这些方法是创建不同类型线程池,从上面的uml图也可以看出Executors是依赖ThreadPoolExecutor去创建不同的线程池

//构造一个固定线程数目的线程池,配置的corePoolSize与maximumPoolSize大小相同,同时使用了一个无
界LinkedBlockingQueue存放阻塞任务,因此多余的任务将存在再阻塞队列,不会由RejectedExecutionHandler处理 
 public static ExecutorService newFixedThreadPool(int var0) {
        return new ThreadPoolExecutor(var0, var0, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue());
    }

构造一个缓冲功能的线程池,配置corePoolSize=0,maximumPoolSize=Integer.MAX_VALUE,keepAliveTime=60s,以及一个无容量的阻塞队列 SynchronousQueue,因此任务提交之后,将会创建新的线程执行;线程空闲超过60s将会销毁 
   public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, 2147483647, 60L, TimeUnit.SECONDS, new SynchronousQueue());
    }

构造一个只支持一个线程的线程池,配置corePoolSize=maximumPoolSize=1,无界阻塞队列LinkedBlockingQueue;保证任务由一个线程串行执行 
   public static ScheduledExecutorService newSingleThreadScheduledExecutor() {
        return new Executors.DelegatedScheduledExecutorService(new ScheduledThreadPoolExecutor(1));
    }


构造有定时功能的线程池,配置corePoolSize,无界延迟阻塞队列DelayedWorkQueue;有意思的是:maximumPoolSize=Integer.MAX_VALUE,由于DelayedWorkQueue是无界队列,所以这个值是没有意义的 
 public static ScheduledExecutorService newSingleThreadScheduledExecutor(ThreadFactory var0) {
        return new Executors.DelegatedScheduledExecutorService(new ScheduledThreadPoolExecutor(1, var0));
    }

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


   

这类还有一个内部类也比较重要,下面是它的代码

   static class DefaultThreadFactory implements ThreadFactory {
        private static final AtomicInteger poolNumber = new AtomicInteger(1);
        private final ThreadGroup group;
        private final AtomicInteger threadNumber = new AtomicInteger(1);
        private final String namePrefix;

        DefaultThreadFactory() {
            SecurityManager var1 = System.getSecurityManager();
            this.group = var1 != null ? var1.getThreadGroup() : Thread.currentThread().getThreadGroup();
            this.namePrefix = "pool-" + poolNumber.getAndIncrement() + "-thread-";
        }

        public Thread newThread(Runnable var1) {
            Thread var2 = new Thread(this.group, var1, this.namePrefix + this.threadNumber.getAndIncrement(), 0L);
            if (var2.isDaemon()) {
                var2.setDaemon(false);
            }

            if (var2.getPriority() != 5) {
                var2.setPriority(5);
            }

            return var2;
        }
    }

其实我们可以看到在为线程池创建线程的时候,其实是运用线程组的概念,来创建,管理线程。

到这里,其实我们大致的理清楚线程池的这些类的关联方式了

猜你喜欢

转载自blog.csdn.net/qq_18416057/article/details/82423802