Java线程池基础介绍

打印 上一主题 下一主题

主题 995|帖子 995|积分 2985

一、线程池的优点

  1、线程池能够复用已经创建了的线程来执行任务,从而降低了频繁创建和销毁线程所带来的资源消耗;
  2、任务创建完成时,不必等待线程的创建,能够立即执行,提高了任务响应的速度。
 
二、创建线程池的七大核心参数

  1、corePoorSize 核心线程数

     线程池中长期存活的线程数量。一般情况下,当线程处于空闲状态时也不会被销毁。
  2、maximumPoorSize 最大线程数


     线程池中允许创建的最大线程数量。当线程池队列满后,能够创建的最大线程数量(核心线程总数量 + 非核心线程总数量)。
  3、keepAliveTime 存活时间

     非核心线程的最大空闲时间。当非核心线程处于空闲状态的时长到达这个时间,就会被销毁。
  4、TimeUnit 时间单位

     存活时间的时间单位。
  5、workQueue 线程池工作队列

     存放工作任务的阻塞队列。当有任务被提交时,若没有线程能够处理,该任务就会被放到队尾,等待线程执行。
  6、threadFactory 线程工厂

     创建一个新的线程时,用到的线程工程。可以用来设置线程名等线程参数。
  7、handler 拒绝策略

     当线程池中的工作线程数量达到了最大线程数量,并且工作队列也容量也满了,此时有任务提交进来时,需要做的处理。
 
三、线程池的执行流程


 如图,线程池的执行策略可以分为三个步骤:
  1、当任务提交时,若此时的工作线程数小于核心线程数,则会创建一个线程来执行任务;
  2、当核心线程数已满时,如果此时阻塞队列没有满,则将任务放入到阻塞队列中,等待线程执行;
  3、若核心线程数和阻塞队列都已满时,会去判断当前线程数是否达到最大线程数,没有达到就会创建一个非核心线程来执行任务,达到就执行拒绝策略。
 
四、常用的四种工作队列

  1、ArrayBlockingQueue 基于数组的有界阻塞队列

    当核心线程数已满,会将新的任务放到队列当中,并按照FIFO的顺序等待线程调度。若队列中的任务达到给定的数值,则会启动新的线程去执行任务,若当前线程数量到达最大线程数量,则拒绝执行任务。
  2、LinkedBlockingQuene 基于链表的无界阻塞队列

    也是按照FIFO的,容量为Integer类型的最大值,所以近似于无界。所以maxPoolSize此时就是无效的,因为队列无界,能够不断添加任务,导致不会去创建非核心线程,线程数量最多等于核心线程数量,达不到最大线程数量。
  3、SynchronousQuene 不缓存任务的阻塞队列

    相当于没有队列,当当前线程数达到corePoolSize时,直接创建非核心线程执行任务,当当前线程数到达maxPoolSize后,则拒绝任务。
  4、PriorityBlockingQueue 具有优先级的无界阻塞队列

    默认情况下,元素采用自然顺序升序排列,也可以自定义类,然后实现compareTo()方法来指定元素排序规则。
 
五、常用的四种拒绝策略

  1、AbortPolicy

    中止策略,直接抛出 RejectedExecutionException 错误。线程池默认使用的策略。
    编写一个简单的执行deno:
  1. public static void main(String[] args) {
  2.         // 创建一个线程池
  3.         ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(2, 5, 3L, TimeUnit.MINUTES, new ArrayBlockingQueue<>(1), new ThreadPoolExecutor.AbortPolicy() );
  4.         for (int i = 0; i < 100; i++) {
  5.             int finalI = i;
  6.             poolExecutor.execute(() -> {
  7.                 try {
  8.                     Thread.sleep(1000);
  9.                     System.out.println("[" + Thread.currentThread().getName() + "]:" + finalI + "同学完成");
  10.                 } catch (InterruptedException e) {
  11.                     e.printStackTrace();
  12.                 }
  13.             });
  14.         }
  15.         poolExecutor.shutdown();
  16.     }
复制代码
     执行结果:达到最大线程数后,直接抛出错误

 
  2、CallerRunsPolicy 

    调用者执行策略,将任务返回给提交该任务的线程执行。
    执行demo不变,将执行策略换为CallerRunsPolicy,运行结果:

     可见,因为我们的main线程提交任务给线程池后,线程池队列及线程数量都已满,便将执行的任务返回给main线程,由main线程执行。
  3、DiscardPolicy

    丢弃策略,将该任务丢弃,且不抛出异常。
    执行demo不变,将执行策略换为DiscardPolicy,运行结果:

     达到最大线程数后,不执行提交的任务。
  4、DiscardOldestPolicy

    丢弃最老的策略,丢弃队列最前面的任务。
    执行demo不变,将执行策略换为DiscardOldestPolicy,运行结果:

     0~5号任务执行过程中,不断有新的任务提交,最后执行到了第99号任务,因为前面的不断被丢弃,99最后被放入队列并被线程执行。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

笑看天下无敌手

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表