Java线程池知识必备

线程池

简介

线程池的创建

new  ThreadPoolExecutor(
int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit milliseconds,
BlockingQueue<Runnable> runnableTaskQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler);
  • corePoolSize(线程池基本大小)

这是一个判断该线程池是否要新建一个新的线程的标准值,如果当前线程池中的线程数小于corePoolSize,
则在接到新的请求任务时新建一个线程来处理,反之则把任务放到
BlockingQueue中,由线程池中空的线程从BlockingQueue中取出并处理;

  • maximumPoolSize(线程池最大大小)

线程池最大的线程数,当大于该值的时候则让RejectedExecutionHandler拒绝处理;

  • keepAliveTime
    当线程池中大于corePoolSize的时候,部分多余的空线程会等待keepAliveTime时间,如果没有请求处理超过该时间则自行销毁;

  • BlockingQueue(任务队列)
    保存等待任务执行的阻塞队列,有以下几种:

    • ArrayBlockingQueue:数组队列,先进先出;
    • LinkedBlockingQueue:链表队列,先进先出,吞吐量大于ArrayBlockingQueue;
    • SynchronousQueue:一个不存储元素的队列,每插入一个任务必须等到另一个线程调用移除操作,否则处于阻塞状态;吞吐量高于LinkedBlockingQueue,newCachedThreadPool使用的就是这个队列;
    • PriorityBlockingQueue:一个优先级无限阻塞的队列;
  • RejectedExecutionHandler(饱和策略)
    当线程池处于饱和状态下,对于提交的新任务必须要有一种策略来处理;

提交任务

  • execute(new Runnable(){} )
    没有返回值

     threadsPool.execute(new Runnable() {
          @Override
          public void run() {
              // TODO Auto-generated method stub
          }
      });
    
  • commit(new callable(){}) 返回future对象

          Future future = mThreadPoolExecutor.submit(new Callable() {
              @Override
              public Object call() throws Exception {
                  return null;
              }
          });
          --------------------------------------------------
    
          try {
              Object o = future.get();//阻塞 直到结果准备就绪
          } catch (InterruptedException e) {
              //中断异常
              e.printStackTrace();
          } catch (ExecutionException e) {
              //无法执行异常
              e.printStackTrace();
          } finally {
              //关闭线程池
              mThreadPoolExecutor.shutdown();
          }
      }
    

关闭任务

  • 原理
    遍历所有的线程,逐个调用线程的interrupt方法来中断线程;
  • shutdown
    执行shutdown后,遍历线程池中所有的线程,将状态修改为SHUTDOWN状态,然后中断正在执行任务的线程;
  • shutdownNow
    执行shutdownNow后,遍历线程池中所有的线程,将所有线程的状态修改为STOP状态,然后尝试停止所有的线程任务

工作原理

  • 工作流程示意图

工作示意图

  • 源码分析

  • 工作线程

合理配置线程池

  • 任务特性

    • 任务的性质:CPU密集型任务,IO密集型的任务,混合型任务;
    • 任务的优先级:高,中,低;
    • 任务的执行时间:长、中、短;
    • 任务的依赖性,是否依赖其他系统资源,比如数据库连接。
  • 配置意见

    • CPU密集型建议使用线程数尽可能少的线程池,IO密集型任务由于线程并不是一直在工作,所以建议使用线程数较多的线程池;
    • 优先级不同任务可以使用PriorityBlockingProcessors任务队列来处理,让优先级更高的来处理(!注意:如果一直是优先级搞的任务在处理,则优先级低的任务可能无法得到处理;
    • 时间不同的任务可以交给不同规模的线程池来处理,也可以交给优先级队列,让时间短的任务先执行;
    • 依赖数据库连接池的任务,由于提交SQL后需要等待返回结果,所以等待的时间越长,CPU空闲的时间越长,为了提高CPU的利用率,可以通过增大线程池的线程数。
    • 建议使用有界队列,这样更加稳定安全,防止撑爆内存(如果线程一直处于阻塞状态,新的任务来的时候就会新建新的线程,直到内存不足)。

线程池的监控

  • 部分线程池的属性参数

    • taskCount:线程池需要执行的任务数量;
    • completedTaskCont: 已经完成的任务数量;
    • largestPoolSize: 线程池曾经创建过的最大线程数,可以看看是否大于最大线程数,是否满过;
    • getPoolSize: 线程池的线程数量,线程池不销毁,池中的线程不会自动销毁
    • getAliveCount:活动状态的线程数。
  • 通过扩展线程池进行监控

    • 继承线程池;
    • 重写beforeExecute,afterExecute和terminated方法。

常用线程池

  • FixedThreadPool 定长并发线程池

    • 源码

      public static ExecutorService newFixedThreadPool(int nThreads) {
          return new ThreadPoolExecutor(nThreads, nThreads,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>());
      }
      
    • 特点:
      可以创建固定的线程数,当线程数达到corePoolSize的时候,再添加任务就放到LinkedBlockingQueue这个无界的队列里边,等待空闲的线程来取任务执行任务,空闲线程不会被回收;
  • SingleThreadExecutor 顺序执行线程池

    • 源码

      public static ExecutorService newSingleThreadExecutor() {
           return new FinalizableDelegatedExecutorService
                              (new ThreadPoolExecutor(1, 1,
                              0L, TimeUnit.MILLISECONDS,
                              new LinkedBlockingQueue<Runnable>()));
      }
      
    • 特点
      corePoolSize为1,既最多只能有一个线程工作,当其他任务来的时候都放到LinkedBlockingQueue任务队列里边,等待线程工作完后,再从队列里边取,逐个执行,相当于顺序执行;
  • CachedThreadPool “无限”容量可缓存线程池

    • 源码

      public static ExecutorService newCachedThreadPool() {
              return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                60L, TimeUnit.SECONDS,
                                new SynchronousQueue<Runnable>());
      }
      
    • 特点
      • SynchronousQueue是一个没有容量的阻塞队列,每个插入必须有对应的移除操作;
      • 如果没有线程去从SynchronousQueue从事移除的工作,那么就会新建一个线程来执行任务,如果一直这么下去,就可以能因为创建过多的线程耗尽CPU资源;
      • 如果空闲的线程等待时间超过60秒,而且没有新的任务,会自动被回收。
  • ScheduledThreadPool 定时线程池

参考资料:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值