• 线程池的用法及思考


    本文介绍下Java中线程池的基本用法,基于此说明如何去确定线程池的大小。

    线程池的创建方法

      newFixedThreadPool

       创建固定线程数的线程池,见下创建代码

      

    /**
         * Creates a thread pool that reuses a fixed number of threads
         * operating off a shared unbounded queue.  At any point, at most
         * {@code nThreads} threads will be active processing tasks.
         * If additional tasks are submitted when all threads are active,
         * they will wait in the queue until a thread is available.
         * If any thread terminates due to a failure during execution
         * prior to shutdown, a new one will take its place if needed to
         * execute subsequent tasks.  The threads in the pool will exist
         * until it is explicitly {@link ExecutorService#shutdown shutdown}.
         *
         * @param nThreads the number of threads in the pool
         * @return the newly created thread pool
         * @throws IllegalArgumentException if {@code nThreads <= 0}
         */
        public static ExecutorService newFixedThreadPool(int nThreads) {
            return new ThreadPoolExecutor(nThreads, nThreads,
                                          0L, TimeUnit.MILLISECONDS,
                                          new LinkedBlockingQueue<Runnable>());
        }
    

        从代码中可发现,corePoolSize和maxPoolSize都是相等的,取决于传入的线程数,keepAliveTime=0代表线程不进行超时回收,但使用的是无界队列,当任务数量过多时,将会导致OOM溢出。

      newSingleThreadPool

      创建线程数为1的线程池,创建代码如下。

      

     /**
         * Creates an Executor that uses a single worker thread operating
         * off an unbounded queue. (Note however that if this single
         * thread terminates due to a failure during execution prior to
         * shutdown, a new one will take its place if needed to execute
         * subsequent tasks.)  Tasks are guaranteed to execute
         * sequentially, and no more than one task will be active at any
         * given time. Unlike the otherwise equivalent
         * {@code newFixedThreadPool(1)} the returned executor is
         * guaranteed not to be reconfigurable to use additional threads.
         *
         * @return the newly created single-threaded Executor
         */
        public static ExecutorService newSingleThreadExecutor() {
            return new FinalizableDelegatedExecutorService
                (new ThreadPoolExecutor(1, 1,
                                        0L, TimeUnit.MILLISECONDS,
                                        new LinkedBlockingQueue<Runnable>()));
        }
    
    
    /**
        * 创建线程数为1的线程池
        *
        */
    

      我们发现corePoolSize和MaxPoolSize都是1,使用的还是无界队列,存在OOM

      newCachedThreadPool

      创建可缓存的线程池。代码如下

      

      /**
         * Creates a thread pool that creates new threads as needed, but
         * will reuse previously constructed threads when they are
         * available.  These pools will typically improve the performance
         * of programs that execute many short-lived asynchronous tasks.
         * Calls to {@code execute} will reuse previously constructed
         * threads if available. If no existing thread is available, a new
         * thread will be created and added to the pool. Threads that have
         * not been used for sixty seconds are terminated and removed from
         * the cache. Thus, a pool that remains idle for long enough will
         * not consume any resources. Note that pools with similar
         * properties but different details (for example, timeout parameters)
         * may be created using {@link ThreadPoolExecutor} constructors.
         *
         * @return the newly created thread pool
         */
        public static ExecutorService newCachedThreadPool() {
            return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                          60L, TimeUnit.SECONDS,
                                          new SynchronousQueue<Runnable>());
    

       从创建代码中发现,corePoolSize核心线程数在一定时间内可以为零,当有一个新的任务时,只需要创建一个存活周期为60秒的线程,使用的是直接队列,队列任务为零,当任务过多时,会创建大量的线程,仍然会导致溢出。

      newScheduledThreadPool

      创建定义任务相关的线程数,在普通线程池的基础上引入了定时任务相关的操作。

      

     /**
         * Creates a new {@code ScheduledThreadPoolExecutor} with the
         * given core pool size.
         *
         * @param corePoolSize the number of threads to keep in the pool, even
         *        if they are idle, unless {@code allowCoreThreadTimeOut} is set
         * @throws IllegalArgumentException if {@code corePoolSize < 0}
         */
        public ScheduledThreadPoolExecutor(int corePoolSize) {
            super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
                  new DelayedWorkQueue());
        }
    

      我们发现可以指定核心线程数,maxPoolSize为Integer.MAX_VALUE,非核心线程数不进行回收,使用了延迟队列,也存在OOM

      workStealingPool

      jdk1.8新增的。产生递归操作时,可使用此线程池。

      综上所述,提供了多种创建线程池的方法,具体使用哪种线程池方法,需要根据实际情况来定,使用多少线程数,最后通过性能测试去确定,我们也可以从CPU密集型和IO密集型方面进行简易区分。CPU密集型的线程数为CPU核心数的1到2倍。IO密集型线程数可为CPU核心数的10倍左右。

      参考计算方法为:线程数=cpu核心数 * (1+ 平均等待时间/平均运行时间)

      

  • 相关阅读:
    [转]Asp.NET MVC Widget开发
    [转]让Windows Server 2008 + IIS 7+ ASP.NET 支持10万并发请求
    [转]jquery Fancybox丰富的弹出层效果
    [转]响应式网页设计:rem、em设置网页字体大小自适应
    [转]jQuery Popup Login and Contact Form
    [转][ASP.NET MVC 小牛之路]12
    [转]jQuery插件实现模拟alert和confirm
    [转]Ionic 实现双击返回键退出功能
    [转]Ionic – Mobile UI Framework for PhoneGap/Cordova Developers
    [转]VS2015 cordova尝试-camera
  • 原文地址:https://www.cnblogs.com/cnxieyang/p/12743444.html
Copyright © 2020-2023  润新知