Java 多线程之自定义线程池(ThreadPool)使用方法
创始人
2024-11-06 02:38:47
0

文章目录

    • 一、概述
    • 二、ThreadPoolExecutor 的作用
    • 三、自定义线程池工创建工厂
    • 四、自定义线程池拒绝策略
    • 五、线程池使用示例

一、概述

  • 线程池是一种管理和复用线程的机制,它包含一组预先创建的线程,用于执行各种任务。线程池的主要作用是提高多线程应用程序的性能和效率,并提供对线程的生命周期和资源的管理,包括线程的创建、销毁和复用。

  • 本文主要讨论线程池执行器(ThreadPoolExecutor)的用法,在观看本文之前建议先看线程池使用入门。

二、ThreadPoolExecutor 的作用

  • ThreadPoolExecutor 的作用是创建线程池。一般情况下,我们使用 Executors 来创建线程池,使用起来非常简单方便。但是他有一个问题,就是创建池时有很参数需要调整时他就不灵活了。Executors 创建线程池本质上也是使用 ThreadPoolExecutor ,所以我们需要了解 ThreadPoolExecutor ,因为他提供了更多和线程池管理控制功能。

  • 下面是使用 ThreadPoolExecutor 创建线程池的示例:

    ThreadPoolExecutor s = new ThreadPoolExecutor(2, 4, 60, TimeUnit.SECONDS,          new ArrayBlockingQueue(4), Executors.defaultThreadFactory(),         new ThreadPoolExecutor.CallerRunsPolicy()); 
  • ThreadPoolExecutor 有7个构造函数,每个参数的用途如下:

    • int corePoolSize, 核心线程数量。线程池中的基本线程数,即在没有任务需要执行时线程池的大小。
    • int maximumPoolSize, 最大线程数量。线程池中允许的最大线程数。
    • long keepAliveTime, 线程生存时间。就是线程在多少时间没有执行任务,就释放线程相关资源。
    • TimeUnit unit, 线程生存时间单位。指定 keepAliveTime 的时间单位。
    • BlockingQueue workQueue, 任务队列。用于保存等待执行的任务的队列。
    • ThreadFactory threadFactory, 线程产生的工厂。用于创建新线程的工厂。
    • RejectedExecutionHandler handler 拒绝策略,就是所有线程都在执行且任务满以后的处理办法。
      • Abort 中止策略。是默认的拒绝策略。当任务无法被接受时,会抛出 RejectedExecutionException 异常
      • Discard 丢弃策略。直接丢弃无法执行的任务,不抛出异常也不通知调用者,一般情况下是不能使用的。
      • DiscardOld 丢弃最老的策略。会丢弃队列中等待时间最长的任务,然后尝试将新任务加入队列。
      • CallerRuns 调用者运行策略。不会抛弃任务,而是将任务返回给调用者,由调用者所在的线程执行。

三、自定义线程池工创建工厂

  • 通过实现 ThreadFactory 接口,实现自定义线池创建工厂。

  • 如下,自定义线程创建工厂,在创建线程时设置线程名称。

        private static void  test2()  {         ThreadFactory  threadFactory = new ThreadFactory(){             @Override             public Thread newThread(Runnable r) {                 Thread thread = new Thread(r);                 thread.setName( "线程-" + thread.getId()); // 设置一个线程名称,方便异常追踪                 // 可以在这里设置其他线程属性,例如优先级、是否为守护线程等                 return thread;             }         };          ThreadPoolExecutor s = new ThreadPoolExecutor(2, 4, 60, TimeUnit.SECONDS,                 new ArrayBlockingQueue(4), threadFactory,                 new ThreadPoolExecutor.CallerRunsPolicy());     } 

四、自定义线程池拒绝策略

  • 通过实现 RejectedExecutionHandler 接口,实现自定义线程池拒绝策略。

  • 如下,我通过自定义线程池拒绝策略,让线程池添加任务数量大于100时,输出一个日志。

    高并发实际应用中你可以记录一个日志文件或数据库,当线程池任务数量小于规定值时重新把任务加入线程池,进行线程池任务恢复,从而防止内存泄露、资源不足等异常产生,保证程序健壮性和稳定性。

        private static void  test1() throws ExecutionException, InterruptedException {         RejectedExecutionHandler rejectedExecutionHandler = new RejectedExecutionHandler(){             @Override             public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {                 if(executor.getQueue().size() > 100){                     System.out.println("线程池任务数量大于100了,要不要限制什么的");                 }             }         };          ThreadPoolExecutor s = new ThreadPoolExecutor(2, 4, 60, TimeUnit.SECONDS,                 new ArrayBlockingQueue(4), Executors.defaultThreadFactory(),                 rejectedExecutionHandler);     } 

五、线程池使用示例

  • 在下面示例中,我创建一个线程池。核心线程数为2个,最大线程数为4个(最多只有4个线程在执行任务),线程空闲存活时间为60秒,使用 ArrayBlockingQueue 保存 Runnable 类型任务,使用默认线程创建工厂和调用者运行拒绝策略。然后添加一个100个任务,每个任务耗时5秒。线程池会执行这些任务,至到结束。

        private static void  test3()  {         ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 4, 60, TimeUnit.SECONDS,                 new ArrayBlockingQueue(4),  Executors.defaultThreadFactory(),                 new ThreadPoolExecutor.CallerRunsPolicy());          for (int i = 1; i <= 100 ; i++) {             final int id = i;             executor.execute(new Runnable() {                 @Override                 public void run() {                     someTask(id);                 }             });         }     }      private static void  someTask(int id){         // 这里是一个复杂的业务逻辑(耗时任务)         try {             Thread.sleep(5000);         } catch (InterruptedException e) {             e.printStackTrace();         }         System.out.println("这里是一个复杂的业务逻辑(耗时任务)"+id);     } 

相关内容

热门资讯

八分钟了解!newpoker怎... 八分钟了解!newpoker怎么安装脚本,哈糖大菠萝能开挂吗,指南书教程(有挂分析)1、哈糖大菠萝能...
方案辅助!微信小程序微乐破解器... 方案辅助!微信小程序微乐破解器2024!解谜真的是有辅助教程(有挂细节)1、进入到微信小程序微乐破解...
第9分钟了解!德普之星有辅助软... 第9分钟了解!德普之星有辅助软件吗,德州局透视脚本,步骤教程(有挂神器)运德普之星有辅助软件吗辅助工...
窍要辅助!洞庭茶苑app辅助!... 窍要辅助!洞庭茶苑app辅助!关于存在有辅助神器(有挂辅助)1.洞庭茶苑app辅助 选牌创建新账号,...
七分钟了解!wepoker怎么... 七分钟了解!wepoker怎么开辅助,wepoker透视脚本免费app,绝活儿教程(有挂细节)1、w...
窍要辅助!嘟咪互动有挂吗!开挂... 窍要辅助!嘟咪互动有挂吗!开挂是有辅助软件(有挂总结)窍要辅助!嘟咪互动有挂吗!开挂是有辅助软件(有...
1分钟了解!wepoker辅助... 1分钟了解!wepoker辅助器最新版本更新内容,德普之星私人局辅助免费,办法教程(有挂辅助)wep...
大纲辅助!心悦海南苹果版辅助器... 大纲辅助!心悦海南苹果版辅助器!关于是有辅助工具(有挂攻略)1、玩家可以在心悦海南苹果版辅助器线上大...
指南辅助!小程序广东雀神智能插... 指南辅助!小程序广东雀神智能插件安装下载!解谜真的是有辅助技巧(新版有挂)运小程序广东雀神智能插件安...
第九分钟了解!wepoker作... 第九分钟了解!wepoker作弊辅助,wpk辅助购买,步骤教程(新版有挂)1、完成wepoker作弊...