01-JDK并发api

java.util.concurrent  作者:Doug Lea   道格·利     

参考博客:

https://juejin.im/entry/5e53e5c1f265da5735504fb6

https://juejin.im/entry/5b6bec4e6fb9a04fe54916c4

一.ThreadPoolExecutor:创建线程池的最全构造方法

public ThreadPoolExecutor(int corePoolSize,//核心线程数
                      int maximumPoolSize,//最大线程数
                      long keepAliveTime,//非核心线程保活时间
                      TimeUnit unit,//时间单位
                      BlockingQueue<Runnable> workQueue,//任务工作队列
                      ThreadFactory threadFactory,//创建线程工程
                      RejectedExecutionHandler handler)//达到最大线程数并且任务工作队列也满时,再提交任务时的处理策略)    

参数说明:  
keepAliveTime:
    当线程空闲时间达到keepAliveTime,该线程会退出,直到线程数量等于corePoolSize。  
    如果allowCoreThreadTimeout设置为true,则所有线程均会退出直到线程数量为0  

allowCoreThreadTimeout:
    是否允许核心线程空闲退出,默认值为false

二.jdk自带的集中线程池

Executors通过静态方法提供4种类型的线程池,他们都是调用ThreadPoolExecutor构造方法创建的

  • Executors.newFixedThreadPool(5)

  • Executors.newCachedThreadPool()

  • Executors.newSingleThreadExecutor()

  • Executors.newScheduledThreadPool(5)

      FixedThreadPool:固定线程池
      public static ExecutorService newFixedThreadPool(int nThreads) {
          return new ThreadPoolExecutor(nThreads, nThreads,
                                        0L, TimeUnit.MILLISECONDS,
                                        new LinkedBlockingQueue<Runnable>());
      }
    
      CachedThreadPool: 缓存线程池
      public static ExecutorService newCachedThreadPool() {
          return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                        60L, TimeUnit.SECONDS,
                                        new SynchronousQueue<Runnable>());
      } 
    
      ScheduledThreadPoolExecutor : 可调度线程池,提供定时、定期方法
      public ScheduledThreadPoolExecutor(int corePoolSize) {
          super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
                new DelayedWorkQueue());
      }
    
      SingleThreadExecutor:单线程线程池
      public static ExecutorService newSingleThreadExecutor() {
          return new FinalizableDelegatedExecutorService
              (new ThreadPoolExecutor(1, 1,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>()));
      }
    注意:  
        1.阿里巴巴java开发手册建议线程池不允许使用Executors去创建,而是通过ThreadPoolExecutors   
          的方式手动创建,这样的处理方式会更加明确线程池的运行规则,避免规则资源耗尽的风险   

        2.根据ThreadPoolExecutors手动创建线程池的方式,各个参数的选择:
                核心线程数:可以根据cpu的核心数考虑:Runtime.getRuntime().availableProcessors()   
                如果应用场景是cpu密集型可以考虑:核心线程数=cpu核数   
                如果应用场景是io密集型可以考虑:核心线程数=cpu核数*2+1 

    说明Executors各个方法的弊端:  

         newFixedThreadPool 和 newSingleThreadExecutor:  
                     主要问题是堆积的请求处理队列可能会耗尽非常大内存,甚至OOM  

         newCachedThreadPool和newScheduleThreadPool:   
                     主要问题是线程最大数是Integer.MAX_VALUE,可能会创建数量非常多的线程,甚至OOM        

三.当一个线程池里的线程异常后,jdk会怎么处理

1.当执行的是execute时,可以看到堆栈异常信息的输出  

2.当执行的是submit时,堆栈异常没有输出。但是调用Future.get()方法时,可以捕获到异常。  

3.不会影响线程池里面其他线程的正常执行   

4.线程池会把异常的线程移除掉,并创建一个新的线程放到线程池中      

四.使用线程池的好处

1.线程的重用  
  java中线程的创建和销毁开销是巨大的,线程池的使用可以减少线程的创建    

2.控制线程池的并发数    
  线程池可以设置核心线程数和最大线程数,所以可以控制最大并发数。   

3.线程池可以对线程进行管理  
  线程池可以提供定时、定期、单线程、并发数控制等功能,比如通过
  ScheduledThreadPool线程池来执行S秒后,没隔N秒执行一次的任务。

Last updated

Was this helpful?