• 创建线程池


    如何创建线程池及处理相应任务

    线程池定义

    线程池就是一个可以复用线程的技术,控制线程和任务的数量;线程池中线程长久存在

    解决的问题(需求)

    用户每发起一个请求,后台就需要创建一个新线程来处理,下次新任务来了肯定又要创建线程处理的,而创建新线程的开销是很大的,并且请求过多时,肯定会产生大量的线程出来,这样会严重影响系统的性能,甚至可能会引起系统瘫痪(宕机)

    工作原理

      
    在这里插入图片描述
      

    实现线程池创建示意图

      
    在这里插入图片描述
      

    重要构造器

      
    在这里插入图片描述
     
    在这里插入图片描述
      

    创建线程池(ExecutorService)

    :通过实现类ThreadPoolExecutor()来创建。

    package com.xie.thread.pool.demo;
    
    import java.util.concurrent.*;
    
    /**
     * 掌握线程池的创建 通过有参构造器创建
     * */
    public class ThreadPoolTest {
        public static void main(String[] args) {
            /**
             * 创建线程池,其各参数具体含义:
             * 参数一:核心线程数量
             * 参数二:最大线程数量
             * 参数三:临时线程存活时间
             * 参数四:参数三的时间单位
             * 参数五:任务队列,此处用于 缓存 来自通信管道的任务的
             * 参数六:线程工厂,用于创建核心线程的
             * 参数七:任务的拒绝策略,此处用到默认策略,直接拒绝的处理方案,当处理不了时,直接抛异常
             * */
            ExecutorService pool = new ThreadPoolExecutor(3, 5, 8,
                    TimeUnit.SECONDS, new ArrayBlockingQueue<>(4), Executors.defaultThreadFactory(),
                    new ThreadPoolExecutor.AbortPolicy());
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    线程池任务处理


    常用API

      
    在这里插入图片描述
      

    :上面为处理处理Runnable任务的API


      
    在这里插入图片描述
      

    :上面为处理处理Callable任务的API


    处理Runnable任务

    Runnable任务类

    package com.xie.thread.pool.task1.pojo;
    
    /**
     * Runnable任务类,线程的任务对象模版
     * */
    public class MyRunnable implements Runnable {
        /**
         * 执行任务区域(即run方法),描述所要执行的任务
         */
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + "==> 输出666~~");
            /** 延迟,模拟业务执行耗时,为了便于观察 */
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    测试

    package com.xie.thread.pool.task1;
    
    import com.xie.thread.pool.task1.pojo.MyRunnable;
    import java.util.concurrent.*;
    /**
     * 处理Runnable任务
     * */
    public class ThreadPoolTest {
        public static void main(String[] args) {
            /**
             * 创建线程池,其各参数具体含义:
             * 参数一:核心线程数量
             * 参数二:最大线程数量
             * 参数三:临时线程存活时间
             * 参数四:参数三的时间单位
             * 参数五:任务队列,此处用于 缓存 来自通信管道的任务的
             * 参数六:线程工厂,用于创建核心线程的
             * 参数七:任务的拒绝策略,此处用到默认策略,直接拒绝的处理方案,当处理不了时,直接抛异常
             * 注:线程池可以一直存活,除非主动去关闭
             * */
            ExecutorService pool = new ThreadPoolExecutor(3, 5, 8,
                    TimeUnit.SECONDS, new ArrayBlockingQueue<>(4), Executors.defaultThreadFactory(),
                    new ThreadPoolExecutor.AbortPolicy());
            // 创建任务对象
            Runnable taskObject = new MyRunnable();
            // 把任务对象 交给 线程池执行。 注:线程池会自动创建一个新线程,自动处理这个任务,自动执行的!
            pool.execute(taskObject);
            pool.execute(taskObject);
            pool.execute(taskObject);
            pool.execute(taskObject);
            pool.execute(taskObject);
            pool.execute(taskObject);
            pool.execute(taskObject);
            // 创建临时线程时机
            pool.execute(taskObject);
            pool.execute(taskObject); /** 对于此线程池来说,此第九个任务为极限值 */
            // 拒绝策略生效时机( 任务数量 > (5 + 4) )
            // pool.execute(taskObject);
            /** 等着 线程池的任务 全部执行完毕后,再关闭线程池 */
            pool.shutdown();
            // 立即关闭线程池! 不管任务是否执行完毕!
            // pool.shutdownNow();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    处理Callable任务

    Callable任务类

    package com.xie.thread.pool.task2.pojo;
    
    import java.util.concurrent.Callable;
    /**
     * 让这个类实现callable接口  Callable任务类
     * */
    public class MyCallable implements Callable<String> {
        private int n;
        public MyCallable(int n) {
            this.n = n;
        }
    
        /** 重写call方法 此为线程池后期调用的 任务方法(call方法) */
        @Override
        public String call() throws Exception {
            // 描述线程要执行的任务,返回线程执行完后的返回结果
            int sum = 0;
            for (int i = 0; i <= n; i++) {
                sum += i;
            }
            return Thread.currentThread().getName() + " 求出了 1-" + n + " 的和是:" + sum;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    测试

    package com.xie.thread.pool.task2;
    
    import com.xie.thread.pool.task2.pojo.MyCallable;
    import java.util.concurrent.*;
    /**
     * 处理Callable任务
     * Callable任务的最大特点:线程池处理任务完后,可以直接获取处理完任务后的结果
     * */
    public class ThreadPoolTest {
        public static void main(String[] args) throws Exception {
            /**
             * 创建线程池,其各参数具体含义:
             * 参数一:核心线程数量
             * 参数二:最大线程数量
             * 参数三:临时线程存活时间
             * 参数四:参数三的时间单位
             * 参数五:任务队列,此处用于 缓存 来自通信管道的任务的
             * 参数六:线程工厂,用于创建核心线程的
             * 参数七:任务的拒绝策略,此处用到默认策略,直接拒绝的处理方案,当处理不了时,直接抛异常
             * 注:线程池可以一直存活,除非主动去关闭
             * */
            ExecutorService pool = new ThreadPoolExecutor(3, 5, 8,
                    TimeUnit.SECONDS, new ArrayBlockingQueue<>(4), Executors.defaultThreadFactory(),
                    new ThreadPoolExecutor.CallerRunsPolicy());
            /** 使用已定义的有参构造器,创建任务对象 Callable对象 并交给线程池 处理
             *  并返回一个未来任务对象
             *  */
            Future<String> futureTask1 = pool.submit(new MyCallable(100));
            Future<String> futureTask2 = pool.submit(new MyCallable(200));
            Future<String> futureTask3 = pool.submit(new MyCallable(300));
            Future<String> futureTask4 = pool.submit(new MyCallable(400));
            Future<String> futureTask5 = pool.submit(new MyCallable(500));
            // 获取执行结果 并打印输出
            System.out.println(futureTask1.get());
            System.out.println(futureTask2.get());
            System.out.println(futureTask3.get());
            System.out.println(futureTask4.get());
            System.out.println(futureTask5.get());
            /** 等着 线程池的任务 全部执行完毕后,再关闭线程池 */
            pool.shutdown();
            /** 测试 */
            // Callable my = new MyCallable(100);
            // System.out.println(my.call());
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    使用工具类(Executors)创建线程池

    常用API

      
    在这里插入图片描述
      

    应用案例

    测试

    package com.xie.thread.pool.tool;
    
    import com.xie.thread.pool.task2.pojo.MyCallable;
    import java.util.concurrent.*;
    /**
     * --->通过工具类Executors创建线程池对象
     * Executors是一个线程池的工具类,提供了很多静态方法用于返回不同特点的线程池对象
     *
     * final关键字(修饰符)作用:
     * 不能被继承,不能被修改???
     *
     * 注:此工具类中这些静态方法的底层,都是通过 线程池的实现类ThreadPoolExecutor 创建 的线程池对象。
     * 使用风险:
     * 大型并发系统环境中使用Executors如果不注意可能会出现系统风险
     * 所以,建议推荐使用 ThreadPoolExecutor()类 来创建线程池。
     *
     * 拓展知识:
     * 核心线程数量配置的参考策略:
     * 1,计算密集型的任务:核心线程数量 = CPU的核数 + 1
     * 2,IO密集型的任务:核心线程数量 = CPU核数 * 2
     * */
    public class ThreadPoolTest {
        public static void main(String[] args) throws Exception {
    
            /** 通过工具类Executors方式 创建 线程池对象 新建固定线程数量的线程池(此处定义为3个) */
            final ExecutorService pool = Executors.newFixedThreadPool(3);
            /** 使用已定义的有参构造器,创建任务对象 Callable对象 并交给线程池 处理
             *  并返回一个未来任务对象
             *  */
            Future<String> futureTask1 = pool.submit(new MyCallable(100));
            Future<String> futureTask2 = pool.submit(new MyCallable(200));
            Future<String> futureTask3 = pool.submit(new MyCallable(300));
            Future<String> futureTask4 = pool.submit(new MyCallable(400));
            Future<String> futureTask5 = pool.submit(new MyCallable(500));
            // 获取执行结果 并打印输出
            System.out.println(futureTask1.get());
            System.out.println(futureTask2.get());
            System.out.println(futureTask3.get());
            System.out.println(futureTask4.get());
            System.out.println(futureTask5.get());
            /** 等着 线程池的任务 全部执行完毕后,再关闭线程池 */
            pool.shutdown();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    :此工具类中的这些静态方法的底层都是通过 线程池的 实现类ThreadPoolExecutor 来创建 线程池对象的。


    拓展

    思考

      
    在这里插入图片描述
      

    任务拒绝策略

      
    在这里插入图片描述
      

    参考视频

    黑马磊哥


  • 相关阅读:
    1111 Online Map
    分享几个查看操作系统版本信息的方法
    OpenHarmony命令行工具hdc_std使用总结
    【云原生之kubernetes实战】Kompose工具的安装使用
    小白学Java
    K8S:pod集群调度及相关操作
    linux-centos虚拟机设置固定ip
    TSINGSEE青犀智能分析网关工服识别算法,如何最大限度保障工人安全?
    用::before伪元素,在文字前面画一个圆形
    【选型】FPGA选型技巧
  • 原文地址:https://blog.csdn.net/m0_69604107/article/details/133546751