线程池的使用(7种创建方法)

2023-11-01

线程池的创建⽅法总共有 7 种,但总体来说可分为 2 类:
        1. 通过 ThreadPoolExecutor 创建的线程池;
        2. 通过 Executors 创建的线程池。
线程池的创建⽅式总共包含以下 7 种(其中 6 种是通过 Executors 创建的, 1 种是通过
ThreadPoolExecutor 创建的):
        1. Executors.newFixedThreadPool:创建⼀个固定⼤⼩的线程池,可控制并发的线程数,超出的线程会在队列中等待;
        2. Executors.newCachedThreadPool:创建⼀个可缓存的线程池,若线程数超过处理所需,缓存⼀段时间后会回收,若线程数不够,则新建线程;
        3. Executors.newSingleThreadExecutor:创建单个线程数的线程池,它可以保证先进先出的执⾏顺序;
        4. Executors.newScheduledThreadPool:创建⼀个可以执⾏延迟任务的线程池;
        5. Executors.newSingleThreadScheduledExecutor:创建⼀个单线程的可以执⾏延迟任务的线程池;

        6. Executors.newWorkStealingPool:创建⼀个抢占式执⾏的线程池(任务执⾏顺序不确定)【JDK1.8 添加】。
        7. ThreadPoolExecutor:最原始的创建线程池的⽅式,它包含了 7 个参数可供设置,后⾯会详细讲。

 1. 固定数量的线程池

public class ThreadPoolDemo3 {
    public static void main(String[] args) {
        ExecutorService threadPool = Executors.newFixedThreadPool(2);
        //添加任务方式 1
        threadPool.submit(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName());
            }
        });

        //添加任务方式2
        threadPool.execute(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName());
            }
        });
    }
}
输出:
pool-1-thread-1
pool-1-thread-2

a.  线程池返回结果

public class ThreadPoolDemo4 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService threadPool =  Executors.newFixedThreadPool(2);
        //执行任务
        Future<Integer> result = threadPool.submit(new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                int num = new Random().nextInt(10);
                System.out.println("随机数" + num);
                return num;
            }
        });

        //打印线程池返回方式
        System.out.println("返回结果:" + result.get());
    }
}
输出
随机数8
返回结果:8

使用submit可以执行有返回值的任务或者是无返回值的任务;而execute只能执行不带返回值的任务。 

b. ⾃定义线程池名称或优先级

public class ThreadPoolDemo5 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
         // 创建线程工厂
        ThreadFactory threadFactory = new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                //!!!!!!!一定要注意:要把任务Runnable设置给新创建的线程
                Thread thread = new Thread(r);
                //设置线程的命名规则
                thread.setName("我的线程" + r.hashCode());
                //设置线程的优先级
                thread.setPriority(Thread.MAX_PRIORITY);
                return thread;
            }
        };
        ExecutorService threadPool = Executors.newFixedThreadPool(2,threadFactory);
        //执行任务1
        Future<Integer> result = threadPool.submit(new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                int num = new Random().nextInt(10);
                System.out.println(Thread.currentThread().getPriority() + ", 随机数:" + num);
                return num;
            }
        });
        //打印线程池返回结果
        System.out.println("返回结果:" + result.get());
    }
}

 提供的功能:

        1. 设置(线程池中)线程的命名规则。

        2. 设置线程的优先级。

        3. 设置线程分组。

        4. 设置线程类型(用户线程、守护线程)。

2. 带缓存的线程池

public class ThreadPoolDemo6 {
    public static void main(String[] args) {
        //创建线程池
        ExecutorService service = Executors.newCachedThreadPool();
        for (int i = 0; i < 10; i++) {
            int finalI = i;
            service.submit(() -> {
                System.out.println("i : " + finalI + "|线程名称:" + Thread.currentThread().getName());
            });
        }
    }
}
输出
i : 1|线程名称:pool-1-thread-2
i : 4|线程名称:pool-1-thread-5
i : 3|线程名称:pool-1-thread-4
i : 5|线程名称:pool-1-thread-6
i : 0|线程名称:pool-1-thread-1
i : 2|线程名称:pool-1-thread-3
i : 6|线程名称:pool-1-thread-7
i : 7|线程名称:pool-1-thread-8
i : 8|线程名称:pool-1-thread-9
i : 9|线程名称:pool-1-thread-1

 优点:线程池会根据任务数量创建线程池,并且在一定时间内可以重复使用这些线程,产生相应的线程池。

缺点:适用于短时间有大量任务的场景,它的缺点是可能会占用很多的资源。

3. 执⾏定时任务

a. 延迟执⾏(⼀次)

public class ThreadPoolDemo7 {
    public static void main(String[] args) {
        //创建线程池
        ScheduledExecutorService service = Executors.newScheduledThreadPool(5);
        System.out.println("添加任务的时间:" + LocalDateTime.now());
        //执行定时任务(延迟3s执行)只执行一次
        service.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("执行子任务:" + LocalDateTime.now());
            }
        },3, TimeUnit.SECONDS);
    }
}
输出
添加任务的时间:2022-04-13T14:19:39.983
执行子任务:2022-04-13T14:19:42.987

  

b. 固定频率执⾏

public class ThreadPoolDemo8 {
    public static void main(String[] args) {
        //创建线程池
        ScheduledExecutorService service = Executors.newScheduledThreadPool(5);
        System.out.println("添加任务时间:" + LocalDateTime.now());
        //2s之后开始执行定时任务,定时任务每隔4s执行一次
        service.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                System.out.println("执行任务:" + LocalDateTime.now());
            }
        },2,4, TimeUnit.SECONDS);
    }
}
输出
添加任务时间:2022-04-13T14:24:38.810
执行任务:2022-04-13T14:24:40.814
执行任务:2022-04-13T14:24:44.814
执行任务:2022-04-13T14:24:48.813
执行任务:2022-04-13T14:24:52.815
执行任务:2022-04-13T14:24:56.813
执行任务:2022-04-13T14:25:00.813
执行任务:2022-04-13T14:25:04.814
执行任务:2022-04-13T14:25:08.813
... ...
... ...
执行任务:2022-04-13T14:26:44.814
执行任务:2022-04-13T14:26:48.813

 注意事项:

public class ThreadPoolDemo9 {
    public static void main(String[] args) {
        //创建线程池
        ScheduledExecutorService service = Executors.newScheduledThreadPool(5);
        System.out.println("添加任务时间:" + LocalDateTime.now());
        service.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                System.out.println("执行任务: " + LocalDateTime.now());
                try {
                    Thread.sleep(5 * 1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },2,4, TimeUnit.SECONDS);
    }
}
输出
添加任务时间:2022-04-13T14:33:34.551
执行任务: 2022-04-13T14:33:36.556
执行任务: 2022-04-13T14:33:41.557
执行任务: 2022-04-13T14:33:46.559
执行任务: 2022-04-13T14:33:51.561
执行任务: 2022-04-13T14:33:56.562
执行任务: 2022-04-13T14:34:01.564
执行任务: 2022-04-13T14:34:06.566
执行任务: 2022-04-13T14:34:11.566
执行任务: 2022-04-13T14:34:16.567
执行任务: 2022-04-13T14:34:21.570
执行任务: 2022-04-13T14:34:26.570
... ....

c. scheduleAtFixedRate VS scheduleWithFixedDelay

scheduleAtFixedRate 是以上⼀次任务的开始时间,作为下次定时任务的参考时间的(参考时间+延迟任务=任务执⾏)。
scheduleWithFixedDelay 是以上⼀次任务的结束时间,作为下次定时任务的参考时间的。
public class ThreadPoolDemo10 {
    public static void main(String[] args) {
        //创建线程池
        ScheduledExecutorService service = Executors.newScheduledThreadPool(5);
        System.out.println("添加任务时间:" + LocalDateTime.now());
        //2s之后开始执行定时任务,定时任务每隔4s执行一次
        service.scheduleWithFixedDelay(new Runnable() {
            @Override
            public void run() {
                System.out.println("执行任务:" + LocalDateTime.now());
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, 2, 4, TimeUnit.SECONDS);
    }
}
输出
添加任务时间:2022-04-13T14:46:02.871
执行任务:2022-04-13T14:46:04.876
执行任务:2022-04-13T14:46:09.878
执行任务:2022-04-13T14:46:14.880
执行任务:2022-04-13T14:46:19.883
执行任务:2022-04-13T14:46:24.885
执行任务:2022-04-13T14:46:29.888
执行任务:2022-04-13T14:46:34.888
执行任务:2022-04-13T14:46:39.891
执行任务:2022-04-13T14:46:44.893
执行任务:2022-04-13T14:46:49.895
执行任务:2022-04-13T14:46:54.897
执行任务:2022-04-13T14:46:59.900
执行任务:2022-04-13T14:47:04.901
... ...

4. 定时任务单线程

public class ThreadPoolDemo11 {
    public static void main(String[] args) {
        ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
        System.out.println("添加任务的时间:" + LocalDateTime.now());
        service.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("执行时间:" + LocalDateTime.now());
            }
        },2, TimeUnit.SECONDS );
    }
}
输出
添加任务的时间:2022-04-13T15:06:38.100
执行时间:2022-04-13T15:06:40.106

5. 单线程线程池

public class ThreadPoolDemo12 {
    public static void main(String[] args) {
        ExecutorService service = Executors.newSingleThreadScheduledExecutor();
        for (int i = 0; i < 10; i++) {
            service.submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println("线程名:" + Thread.currentThread().getName());
                }
            });
        }
    }
}
输出
线程名:pool-1-thread-1
线程名:pool-1-thread-1
线程名:pool-1-thread-1
线程名:pool-1-thread-1
线程名:pool-1-thread-1
线程名:pool-1-thread-1
线程名:pool-1-thread-1
线程名:pool-1-thread-1
线程名:pool-1-thread-1
线程名:pool-1-thread-1

(MS) 为什么不直接用线程?

单线程的线程池又什么意义?

        1. 复用线程。

        2. 单线程的线程池提供了任务队列和拒绝策略(当任务队列满了之后(Integer.MAX_VALUE),新来的任务就会拒绝策略)

6. 根据当前CPU⽣成线程池

public class ThreadPoolDemo13 {
    public static void main(String[] args) {
        ExecutorService service = Executors.newWorkStealingPool();
        for (int i = 0; i < 10; i++) {
            service.submit(() -> {
                System.out.println("线程名" + Thread.currentThread().getName());
            });
            
            while(!service.isTerminated()) {
            }
        }
    }
}
输出
线程名ForkJoinPool-1-worker-1

7. ThreadPoolExecutor

线程池的使用(7种创建方法)_Youcan.的博客-CSDN博客https://blog.csdn.net/m0_48273471/article/details/124171220

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

线程池的使用(7种创建方法) 的相关文章

随机推荐

  • DispatcherServlet是如何进行初始化的呢?

    转自 DispatcherServlet是如何进行初始化的呢 下文笔者讲述DispatcherServlet的初始化顺序 如下所示 Web容器启动时将调用HttpServletBean的init方法 public abstract clas
  • 蓝桥杯真题:乘积尾零

    题目描述 本题为填空题 只需要算出结果后 在代码中使用输出语句将所填结果输出即可 如下的 10 行数据 每行有 10 个整数 请你求出它们的乘积的末尾有多少个零 5650 4542 3554 473 946 4114 3871 9073 9
  • java 通过url取得文件返回InputStream类型数据的工具类

    通过url取得文件返回InputStream类型数据 author gugf public class HttpUtils 通过图片url返回图片Bitmap param url return public static InputStre
  • 基于RTMP实现Linux

    背景 Windows操作系统自问世以来 以其简单易用的图形化界面操作受到大众追捧 为计算机的普及 科技的发展做出了不可磨灭的功绩 也慢慢的成为人们最依赖的操作系统 在中国 90 以上的办公环境都是Windows 学校和各种培训班的培训内容也
  • ruoyi导入excel报错数据越界

    一 报错截图 二 报错原因 实体类 三 修改方式 将实体类Excel注释 修改去掉 readConverterExp部分 重新导入后成功 四 出错原因
  • 计算机的内存

    物理内存 内存是电脑的一个硬件组成部分 从单片机的组成我们可以看到 CPU 内存和输入输出接口 就组成一个完整的电脑 其他统统属于外设 内存是可以被CPU通过总线进行操作的 也就是与CPU之间有总线相连接的 电脑所有的输入输出 都是要从内存
  • Nodejs

    一 是什么 在浏览器事件循环 opens new window 中 我们了解到javascript在浏览器中的事件循环机制 其是根据HTML5定义的规范来实现 而在NodeJS中 事件循环是基于libuv实现 libuv是一个多平台的专注于
  • 帮我写一段库存管理的程序

    答 下面是一段库存管理的程序 定义变量 int 库存总量 0 计算库存总量 for int i 0 i lt 产品列表 length i 库存总量 库存总量 产品列表 i 库存数量 打印库存总量 System out println 库存总
  • 详解Win10家庭版/专业版/企业版功能区别

    Win10版本到底有哪些 Win10的各版本有什么不同 差别和区别 Win10旗舰版有木有 Win10最好的版本是哪个 我应该用哪个版本的Windows10 之前曾经在今年更早时间解释了Win10各个版本之间有什么差别和不同之处 但是在Wi
  • Java 线程

    线程 创建线程的方式及实现 https www cnblogs com 3s540 p 7172146 html sleep join yield 有什么区别 https blog csdn net xiangwanpeng article
  • 怎么让chatGPT写作文-ChatGPT如何写作

    chatGPT写文章攻略 ChatGPT 可以生成文章的概要 但生成的文章质量和效率与输入的信息质量和有效性有着重要关系 以下是使用 ChatGPT 写作时需要注意的攻略 确定写作主题和目的 在开始使用 ChatGPT 进行写作前 需要明确
  • Office2019 Office2016 Office2010 Office365 系列各版本下载

    蓝点网出品 必属精品 Office Tools Plus 相信很多博文都有写教程 然鹅 软件里就有 很详细 实在激活不了加群 有小姐姐远程技术支持还免费 之前的那篇博文链接失效且因为下载链接的原因被删 这回 下载链接见评论
  • linux查看ipynb文件

    linux查看ipynb文件 使用jupyter查看 使用jupyter查看 安装 pip install jupyter 添加配置好的环境到jupyter notebook的kernel中 python m ipykernel insta
  • 1016 部分A+B

    正整数 A 的 DA 为 1 位整数 部分 定义为由 A 中所有 DA 组成的新整数 PA 例如 给定 A 3862767 DA 6 则 A 的 6 部分 PA 是 66 因为 A 中有 2 个 6 现给定 A DA B DB 请编写程序计
  • python自动化测试web页面组成_Selenium自动化测试网页

    今天想跟大家分享的是 关于selenium的自动化测试一些基础的东西 安装环境 1 Python环境 安装完成后通过Windows命令提示符CMD输入 python 查看是否安装成功 2 安装setuptools与pip setuptool
  • markdown 矩阵

    无括号 begin matrix 1 2 3 4 5 6 7 8 9 end matrix 1 2
  • VUE3 + Ant Design Vue构建

    步骤 node 和 npm 已安装前提下 1 安装vue 安装vue脚手架 npm install g vue cli 安装vue vue create 项目名 2 安装Ant Design Vue 最好安装的时候不要用pnpm 我用pnp
  • 内存分区-包含bss段data段

    都说四大内存分区 代码区 全局区 堆区 栈区 但是这个说法比较粗略 其实从低地址 gt 高地址 依次为代码区 常量 全局变量和静态变量 bss段 堆区 栈区 代码区 常量 const define 全局区 data段 静态变量和初始化的全局
  • RabbitMQ--基础--11.2--幂等性,惰性队列

    RabbitMQ 基础 11 2 幂等性 惰性队列 1 幂等性 就是重复消费消息 1 1 消息重复消费 消费者在消费MQ中的消息时 MQ已把消息发送给消费者 消费者在给MQ返回ack时网络中断 故MQ未收到确认消息 该条消息会重新发给其它的
  • 线程池的使用(7种创建方法)

    目录 1 固定数量的线程池 a 线程池返回结果 b 定义线程池名称或优先级 2 带缓存的线程池 3 执 定时任务 a 延迟执 次 b 固定频率执 c scheduleAtFixedRate VS scheduleWithFixedDelay