在Java的高并发领域,线程池一直是一个无法回避的话题。有些童鞋一直在使用线程池,但是如何创建线程池只停留在使用Executors工具类的方式上。那么,创建线程池的方法有哪些呢?下面我们从创建线程池的源代码来深入分析一下有哪些创建线程池的方法。
使用Executors工具类创建一个线程池。
在创建线程池时,初学者使用最多的是工具类Executors,使用这个工具类创建线程池非常简单。不需要过多关注线程池的细节,只需要传入必要的参数即可。Executors工具类提供了几种创建线程池的方法,如下所示。
Executors.newCachedThreadPool:创建一个可缓存的线程池,如果线程池的大小超过了需要,可以灵活回收空闲线程,如果没有可回收线程,则新建线程Executors.newFixedThreadPool:创建一个定长的线程池,可以控制线程的最大并发数,超出的线程会在队列中等待Executors.newScheduledThreadPool:创建一个定长的线程池,支持定时、周期性的任务执行Executors.newSingleThreadExecutor:创建一个单线程化的线程池,使用一个唯一的工作线程执行任务,保证所有任务按照指定顺序(先入先出或者优先级)执行Executors.newSingleThreadScheduledExecutor:创建一个单线程化的线程池,支持定时、周期性的任务执行Executors.newWorkStealingPool:创建一个具有并行级别的work-stealing线程池
其中
executors . newworksealingpool方法是Java 8中创建线程池的新方法,可以为线程池设置并行级别,具有更高的并发性和性能。除了这个方法,其他创建线程池的方法本质上都是调用ThreadPoolExecutor类的构造方法。
例如,我们可以使用下面的代码来创建一个线程池。
Executors.newWorkStealingPool();Executors.newCachedThreadPool();Executors.newScheduledThreadPool(3);
使用ThreadPoolExecutor类创建线程池
从代码结构上看,ThreadPoolExecutor类继承自AbstractExecutorService,也就是说,ThreadPoolExecutor类具有AbstractExecutorService类的所有功能。
由于Executors工具类中创建的线程池大多调用ThreadPoolExecutor类的构造函数,所以我们也可以直接调用ThreadPoolExecutor类的构造函数来创建线程池,而不使用Executors工具类。接下来,我们来看看ThreadPoolExecutor类的构造方法。
ThreadPoolExecutor类中的所有构造方法如下所示。
public ThreadPoolExecutor(int corePoolSize, int ***ximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {this(corePoolSize, ***ximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), defaultHandler);}public ThreadPoolExecutor(int corePoolSize,int ***ximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) {this(corePoolSize, ***ximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, defaultHandler);}public ThreadPoolExecutor(int corePoolSize,int ***ximumPoolSize,long keepAliveTime, TimeUnit unit,BlockingQueue<Runnable> workQueue,RejectedExecutionHandler handler) {this(corePoolSize, ***ximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), handler);}public ThreadPoolExecutor(int corePoolSize,int ***ximumPoolSize,long keepAliveTime,TimeUnit unit, BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler) {if (corePoolSize < 0 ||***ximumPoolSize <= 0 ||***ximumPoolSize < 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.***ximumPoolSize = ***ximumPoolSize;this.workQueue = workQueue;this.keepAliveTime = unit.toNanos(keepAliveTime);this.threadFactory = threadFactory;this.handler = handler;}
根据ThreadPoolExecutor类构造方法的源代码,最终调用创建线程池的构造方法如下。
public ThreadPoolExecutor(int corePoolSize, int ***ximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) {if (corePoolSize < 0 ||***ximumPoolSize <= 0 ||***ximumPoolSize < 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.***ximumPoolSize = ***ximumPoolSize;this.workQueue = workQueue;this.keepAliveTime = unit.toNanos(keepAliveTime);this.threadFactory = threadFactory;this.handler = handler;}
关于该构造方法中各参数的意义和作用,可以参考《高并发——线程池和ThreadPoolExecutor类的分析》。
可以调用ThreadPoolExecutor类的构造函数来创建线程池。例如,我们可以用下面的形式创建一个线程池。
new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>());
使用ForkJoinPool类创建线程池
在Java8的Executors工具类中,添加了以下创建线程池的方法。
public static ExecutorService newWorkStealingPool(int paralleli***) {return new ForkJoinPool(paralleli***, ForkJoinPool.defaultForkJoinWorkerThreadFactory, null, true);}public static ExecutorService newWorkStealingPool() {return new ForkJoinPool(Runtime.getRuntime().availableProcessors(), ForkJoinPool.defaultForkJoinWorkerThreadFactory, null, true);}
从源代码上看,本质上可以调用ForkJoinPool类的构造方法类来创建线程池,从代码结构上看,ForkJoinPool类继承了AbstractExecutorService抽象类。接下来,我们来看看ForkJoinPool类的构造方法。
public ForkJoinPool() {this(Math.min(MAX_CAP, Runtime.getRuntime().availableProcessors()), defaultForkJoinWorkerThreadFactory, null, false);} public ForkJoinPool(int paralleli***) {this(paralleli***, defaultForkJoinWorkerThreadFactory, null, false);}public ForkJoinPool(int paralleli***,ForkJoinWorkerThreadFactory factory,UncaughtExceptionHandler handler,boolean asyncMode) {this(checkParalleli***(paralleli***), checkFactory(factory), handler, asyncMode ? FIFO_QUEUE : LIFO_QUEUE, "ForkJoinPool-" + nextPoolId() + "-worker-");checkPermission();}private ForkJoinPool(int paralleli***, ForkJoinWorkerThreadFactory factory, UncaughtExceptionHandler handler, int mode, String workerNamePrefix) {this.workerNamePrefix = workerNamePrefix;this.factory = factory;this.ueh = handler;this.config = (paralleli*** & SMASK) | mode;long np = (long)(-paralleli***); // offset ctl countsthis.ctl = ((np << AC_SHIFT) & AC_MASK) | ((np << TC_SHIFT) & TC_MASK);}
通过看源代码,我们知道ForkJoinPool的构造方法最后调用了下面的私有构造方法。
private ForkJoinPool(int paralleli***, ForkJoinWorkerThreadFactory factory, UncaughtExceptionHandler handler, int mode, String workerNamePrefix) {this.workerNamePrefix = workerNamePrefix;this.factory = factory;this.ueh = handler;this.config = (paralleli*** & SMASK) | mode;long np = (long)(-paralleli***); // offset ctl countsthis.ctl = ((np << AC_SHIFT) & AC_MASK) | ((np << TC_SHIFT) & TC_MASK);}
其中,各参数的含义如下。
paralleli***:并发级别。factory:创建线程的工厂类对象。handler:当线程池中的线程抛出未捕获的异常时,统一使用UncaughtExceptionHandler对象处理。mode:取值为FIFO_QUEUE或者LIFO_QUEUE。workerNamePrefix:执行任务的线程名称的前缀。
当然,私有构造方法虽然参数最多,但不会直接公开外部方法。我们可以用下面的方法创建一个线程池。
new ForkJoinPool();new ForkJoinPool(Runtime.getRuntime().availableProcessors());new ForkJoinPool(Runtime.getRuntime().availableProcessors(), ForkJoinPool.defaultForkJoinWorkerThreadFactory, null, true);
使用ScheduledThreadPoolExecutor类创建线程池。
以下方法类存在于Executors工具类中,用于创建线程池。
public static ScheduledExecutorService newSingleThreadScheduledExecutor() {return new DelegatedScheduledExecutorService(new ScheduledThreadPoolExecutor(1));}public static ScheduledExecutorService newSingleThreadScheduledExecutor(ThreadFactory threadFactory) {return new DelegatedScheduledExecutorService(new ScheduledThreadPoolExecutor(1, threadFactory));}public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {return new ScheduledThreadPoolExecutor(corePoolSize);}public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize, ThreadFactory threadFactory) {return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory);}
从源代码来看,这些方法实际上调用了
ScheduledThreadPoolExecutor类的构造方法。scheduledthreadpoolexecutor中存在的构造方法如下。
public ScheduledThreadPoolExecutor(int corePoolSize) {super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue());}public ScheduledThreadPoolExecutor(int corePoolSize, ThreadFactory threadFactory) {super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue(), threadFactory);}public ScheduledThreadPoolExecutor(int corePoolSize, RejectedExecutionHandler handler) {super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue(), handler);}public ScheduledThreadPoolExecutor(int corePoolSize,ThreadFactory threadFactory, RejectedExecutionHandler handler) {super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue(), threadFactory, handler);}
在代码结构上,
scheduledthreadpoolexecutor类继承了threadpooleexecutor类,本质上是调用threadpooleexecutor类的构造方法,只是此时传递的队列是DelayedWorkQueue。我们可以直接调用ScheduledThreadPoolExecutor类的构造函数来创建一个线程池,比如用下面的形式创建一个线程池。
new ScheduledThreadPoolExecutor(3)
本文来自我要无比强大投稿,不代表舒华文档立场,如若转载,请注明出处:https://www.chinashuhua.cn/24/545364.html