线程池

一、线程池

  • 为什么要使用线程池:在一个应用程序中,我们需要多次使用线程,也就意味着要多次创建并销毁线程。而且创建并销毁线程的过程势必会损耗内存。

  • 什么是线程池:java中出现了一种管理线程的概念,可以方便的管理线程,用一个拿一个,用完在放回到线程池中,这样可以减少内存的损耗。

  • 如何创建一个线程池

    • java中已经提供了创建线程的一个类:Executor;但在创建线程池时,使用它的子类:

      hreadPoolExecutor、AbstractExecutorService、ExecutorService和Executor几个之间的关系
      
        a、Executor是一个顶层接口,在它里面只声明了一个方法execute(Runnable),返回值为void,参数为Runnable类型,从字面意思可以理解,就是用来执行传进去的任务的;
      
        b、然后ExecutorService接口继承了Executor接口,并声明了一些方法:submit、invokeAll、invokeAny以及shutDown等;
      
        c、抽象类AbstractExecutorService实现了ExecutorService接口,基本实现了ExecutorService中声明的所有方法;
      
        d、然后ThreadPoolExecutor继承了类AbstractExecutorService。
      //ThreadPoolExecutor类中几个重要的方法
      execute()
      
      submit()
      
      shutdown();
      
      shutdownNow();
      
      public ThreadPoolExecutor(
      			  int corePoolSize,  
                    int maximumPoolSize, 
                    long keepAliveTime, 
                    TimeUnit unit,  
                    BlockingQueue<Runnable> workQueue,  
                    ThreadFactory threadFactory,                     RejectedExecutionHandler handler)
      ————————————————
      这是其中最重要的一个构造方法,这个方法决定了创建出来的线程池的各种属性。
      corePoolSize:线程池中核心线程数量,核心线程就是无任务状态下也不可以清除。
      maximumPoolSize:线程池中可以容纳的最大线程数量。
      keepAliveTime:线程池中除核心线程之外的其他线程可以存活的时间。
      	如果调用了allowCoreThreadTimeOut(boolean)方法,在线程池中的线程数不大于corePoolSize时,keepAliveTime参数也会起作用,直到线程池中的线程数为0;
      util:计算时间的单位。7中静态属性
      	TimeUnit.DAYS;               //天
          TimeUnit.HOURS;             //小时
          TimeUnit.MINUTES;           //分钟
          TimeUnit.SECONDS;           //秒
          TimeUnit.MILLISECONDS;      //毫秒
          TimeUnit.MICROSECONDS;      //微妙
          TimeUnit.NANOSECONDS;       //纳秒
      workQueue:等待队列,任务可以存储在任务队列中等待被执行,执行的原则就是FIFO。
      	等待队列类型:
      	ArrayBlockingQueue:基于数组的先进先出队列,此队列创建时必须指定大小;
          LinkedBlockingQueue:基于链表的先进先出队列,如果创建时没有指定此队列大小,则默认为Integer.MAX_VALUE;
          SynchronousQueue:这个队列比较特殊,它不会保存提交的任务,而是将直接新建一个线程来执行新来的任务;
      threadFactory:创建线程的线程工厂。
      handler:是一种拒绝策略,可以在任务满了以后,拒绝某些任务。
      
  • 线程池执行流程

    1. 首先执行判断,判断核心线程是否处于空闲状态,
    2. 如果不是,核心线程就先就执行任务,
    3. 如果核心线程已满,则判断任务队列是否有地方存放该任务,
    4. 若果有,就将任务保存在任务队列中,等待执行,
    5. 如果满了,在判断最大可容纳的线程数,
    6. 如果没有超出这个数量,就开创非核心线程执行任务,
    7. 如果超出了,就调用handler实现拒绝策略(四种执行策略)。
      • 第一种ThreadPoolExecutor.AbortPolicy:不执行新任务,直接抛出异常,提示线程池已满。
      • 第二种ThreadPoolExecutor.DisCardPolicy:不执行新任务,也不抛出异常。
      • 第三种ThreadPoolExecutor.DisCardOldSetPolicy:将消息队列中的第一个任务替换为当前新进来的任务执行。
      • 第四种ThreadPoolExecutor.CallerRunsPolicy:直接调用execute来执行当前任务。
  • 四种常见线程池类型:

    1. achedThreadPool:可缓存的线程池,该线程池中没有核心线程,非核心线程的数量为Integer.max_value,就是无限大,当有需要时创建线程来执行任务,没有需要时回收线程,适用于耗时少,任务量大的情况。
    2. SecudleThreadPool:周期性执行任务的线程池,按照某种特定的计划执行线程中的任务,有核心线程,但也有非核心线程,非核心线程的大小也为无限大。适用于执行周期性的任务。
    3. SingleThreadPool:只有一条线程来执行任务,适用于有顺序的任务的应用场景。
    4. FixedThreadPool:定长的线程池,有核心线程,核心线程的即为最大的线程数量,没有非核心线程。
  • java doc中,并不提倡我们直接使用ThreadPoolExecutor,而是使用Executors类中提供的几个静态方法来创建线程池:

    Executors.newCachedThreadPool();        //创建一个缓冲池,缓冲池容量大小为Integer.MAX_VALUE
    
    Executors.newSingleThreadExecutor();   //创建容量为1的缓冲池
    
    Executors.newFixedThreadPool(int);    //创建固定容量大小的缓冲池
    
    //三个静态方法的具体实现;
    public static ExecutorService newFixedThreadPool(int nThreads) {
    
        return new ThreadPoolExecutor(nThreads, nThreads,
    
                                      0L, TimeUnit.MILLISECONDS,
    
                                      new LinkedBlockingQueue<Runnable>());
    
    }
    
    public static ExecutorService newSingleThreadExecutor() {
    
        return new FinalizableDelegatedExecutorService
    
            (new ThreadPoolExecutor(1, 1,
    
                                    0L, TimeUnit.MILLISECONDS,
    
                                    new LinkedBlockingQueue<Runnable>()));
    
    }
    
    public static ExecutorService newCachedThreadPool() {
    
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
    
                                      60L, TimeUnit.SECONDS,
    
                                      new SynchronousQueue<Runnable>());
    
    
         60L, TimeUnit.SECONDS,
    
                                      new SynchronousQueue<Runnable>());
    
    }
    
    
    
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值