线程池简单案例

2023-05-16

线程池使用案例

    • 一、Executors
    • 1、newFixedThreadPool
    • 2、newCachedThreadPool
    • 3、newSingleThreadExecutor
    • 4、newScheduledThreadPool
    • 二、ThreadPoolExecutor
    • 三、两种线程池创建方式的异同
    • 四、返回值
    • 五、一个简单实例

线程池创建方式

一、Executors

1、newFixedThreadPool

1.1 创建固定大小的线程池。
1.2 创建方式:ExecutorService fixedTp= Executors.newFixedThreadPool(int count);
1.3 适用场景:执行长期的任务

2、newCachedThreadPool

2.1 创建一个不限线程数上限的线程池,任何提交的任务都将立即执行
2.2 创建方式:ExecutorService cachedTp = Executors.newCachedThreadPool();
2.3 适用场景:执行很多短期异步的小程序或者负载较轻的服务器	

3、newSingleThreadExecutor

3.1 创建只有一个线程的线程池,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行		
3.2 创建方式:ExecutorService SingleTp = Executors.newSingleThreadExecutor();	
3.3 适用场景:一个任务一个任务执行的场景

4、newScheduledThreadPool

4.1 创建一个可定期或者延时执行任务的定长线程池,支持定时及周期性任务执行。
4.2 创建方式:ScheduledExecutorService schedTp= Executors.newScheduledThreadPool(5);
4.3 适用场景:周期性执行任务的场景
创建一个定长的线程池,线程池可以周期性或延迟执行如下:
 (1)  scheduledTp.schedule(r1, 5, TimeUnit.SECONDS);//延迟3秒后执行r1
 (2)  scheduledTp.scheduleAtFixedRate(r2,5,3,TimeUnit.SECONDS);//延迟5秒后每3秒执行一次r2

二、ThreadPoolExecutor

Executors创建线程池的快捷方法,实际上是调用了ThreadPoolExecutor的构造方法

 public ThreadPoolExecutor(
 int corePoolSize, // 线程池长期维持的线程数,即使线程处于Idle状态,也不会回收。
 int maximumPoolSize, // 线程数的上限
 long keepAliveTime, TimeUnit unit, // 超过corePoolSize的线程的idle时长,
                                    // 超过这个时间,多余的线程会被回收。
 BlockingQueue<Runnable> workQueue, // 任务的排队队列
 ThreadFactory threadFactory, // 新线程的产生方式
 RejectedExecutionHandler handler) // 拒绝策略
 
 举例:
 ExecutorService executorService = new ThreadPoolExecutor(2, 2, 0, TimeUnit.SECONDS, 
 new ArrayBlockingQueue<>(512), // 使用有界队列,避免OOM
 new ThreadPoolExecutor.DiscardPolicy());//DiscardPolicy 对溢出队列的任务不做处理,直接忽略
其他拒绝策略
AbortPolicy	 抛出RejectedExecutionException(默认)
DiscardOldestPolicy  丢弃执行队列中最老的任务,尝试为当前提交的任务腾出位置
CallerRunsPolicy	直接由提交任务者执行这个任务

三、两种线程池创建方式的异同

	1、Executors.newXXXThreadPool()快捷方法创建线程池,这种方式使用无界的任务队列,容易造成OOM
	建议使用ThreadPoolExecutor的构造方法手动指定各项参数。
	2、提交任务的类型分为Runnable和Callable 二者区别如下:
	 2.1 方法签名不同,void Runnable.run(), V Callable.call() throws Exception
	 2.2 是否允许有返回值,Callable允许有返回值
	 2.3 是否允许抛出异常,Callable允许抛出异常。
	提交任务的方式:
	Future<T> submit(Callable<T> task)	有返回值
	void execute(Runnable command)	无返回值
	Future<?> submit(Runnable task)	虽然返回Future,但是其get()方法总是返回null

四、返回值

1、获取单个结果
用submit()向线程池提交任务后会返回一个Future,Future.get()方法能够阻塞等待执行结果,
get(long  timeout, TimeUnit unit)方法可以指定等待的超时时间。

2、获取多个结果
如果向线程池提交了多个任务,要获取这些任务的执行结果,可以依次调用Future.get()获得。
对于这种场景,使用ExecutorCompletionService,该类的take()方法总是阻塞等
待某一个任务完成,然后返回该任务的Future对象。向CompletionService批量提交任务后,
只需调用相同次数的CompletionService.take()方法,就能获取所有任务的执行结果。

   List<Object>lists=new ArrayList<>();
   ExecutorService executorService = new ThreadPoolExecutor(2, 2, 0, TimeUnit.SECONDS, 
   new ArrayBlockingQueue<>(512), // 使用有界队列,避免OOM
   new ThreadPoolExecutor.DiscardPolicy());
   CompletionService<Object> cs= new ExecutorCompletionService<Object>(executorService );
   for (Callable<Object> s : lists)// 提交所有任务
     cs.submit(s);
   int n = lists.size();
   for (int i = 0; i < n; ++i) {// 获取每一个完成的任务
       Object r = cs.take().get();
       if (r != null)
        //一些操作
   }

五、一个简单实例

模拟发送消息
public class ExecutorTest {
   
    //核心线程数
    int poolSize = Runtime.getRuntime().availableProcessors() * 2;
    //任务队列
    BlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(512);
    //拒绝策略
    RejectedExecutionHandler policy = new ThreadPoolExecutor.DiscardPolicy();
     //创建线程池
    ExecutorService service = new ThreadPoolExecutor(poolSize, poolSize,
    0, TimeUnit.SECONDS, queue, policy);

public static void main(String[] args) {
    ExecutorTest pmt = new ExecutorTest();
    //待接收人
    List<Integer> receivers = new ArrayList<>();
    for (int i = 0; i < 100; i++) {
        receivers.add(i);
    }
    String content = "群发消息_测试代码";
    int successCount = pmt.sendMsg(receivers, content); //使用线程池处理发送任务
    System.out.println("共有[" + receivers.size() + "]接收者,发送成功["+successCount+"]");
}

public int sendMsg(List<Integer> data, String content) {
        long begin = System.nanoTime();//开始时间
        AtomicInteger ai = new AtomicInteger(0);//原子性计数
        // 获取多个返回结果
        CompletionService<Integer> ecs = new ExecutorCompletionService<>(service);
        //循环发送消息
        for (int i = 0, len = data.size(); i < len; i++) {
            Integer dataReceiver = data.get(i);
            ecs.submit(() -> {
                //模拟调用相对比较耗时的发送消息接口
                Thread.sleep(100);
                //发送消息
                int result = sendMsg(dataReceiver, content);
                System.out.println("接收者["+dataReceiver + "], 执行结果["+result+"]");
                return result;
            });
        }
        System.out.println("-----" + (System.nanoTime() - begin) / 1000_000d + "-----");
        //循环获得执行结果
        int length = data.size();
        for (int i = 0; i < length; i++) {
            try {
                int resultStatus = ecs.take().get();
                if (resultStatus == 0) { //发送成功
                    ai.incrementAndGet();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    System.out.println("发送消息结束,耗时:" + (System.nanoTime() - begin) / 1000_000d);
    service.shutdown();//关闭线程池
        try {
            if (!service.awaitTermination(30, TimeUnit.SECONDS)) {
                System.out.println(" 到达指定时间,还有线程没执行完,不再等待,关闭线程池!");
                // 调用 shutdownNow 取消正在执行的任务
                service.shutdownNow();
                // 再次等待 60 s,如果还未结束,可以再次尝试,或则直接放弃
                if (!service.awaitTermination(60, TimeUnit.SECONDS))
                    System.err.println("线程池任务未正常执行结束");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return ai.get();//返回成功发送的次数
    }

//完成发送消息
private int sendMsg(Integer receiver, String content) {
    if (receiver % 2 == 0) {//模拟被2整除,即为发送成功
        return 0;
    }
    return 1;
}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

线程池简单案例 的相关文章

随机推荐

  • 【Elasticsearch】Elasticsearch日志场景最佳实践

    1 概述 转载 xff1a Day 12 Elasticsearch日志场景最佳实践 相似文章 xff1a Elasticsearch Elasticsearch 最佳实践系列之分片恢复并发故障 Elasticsearch可广泛应用于日志分
  • centos7 通过kvm+vnc 实现远程桌面虚拟化和创建windows、Linux虚拟机

    感谢朋友支持本博客 xff0c 欢迎共同探讨交流 xff0c 由于能力和时间有限 xff0c 错误之处在所难免 xff0c 欢迎指正 xff01 如果转载 xff0c 请保留作者信息 博客地址 xff1a http blog csdn ne
  • OpenStack Newton 新功能介绍

    以下下摘录自三位朋友的文章 http chenxiang baijia baidu com article 647457 http tutorials hostucan cn openstack newton publish http lc
  • 使用51单片机驱动无源蜂鸣器按一定频率发声

    由于不同的延时函数对频率计算中的各种数值有不同的影响 xff0c 因此 xff0c 首先说明我使用的延时函数 delay us 10000 xff09 大约 0 12秒 span class token keyword void span
  • 解决访问centos虚拟机中MySQL非常慢的问题

    参考网址 MySQL之 解决远程连接mysql很慢的方法 mysql connect 打开连接慢 Centos 7 中yum安装Mysql和修改mysql配置 具体解决方法 xff1a 1 启动centos虚拟机 2 打开终端程序 xff0
  • Ubuntu 18.04使用过程遇到的问题

    文章目录 pipy 下载numpy文件连接超时使用conda pip 安装文件出错opencv 43 python 无法关闭打开的窗口opencv 43 python 保存视频出错numpy版本过高 xff0c 出现警告解决方法 pipy
  • 前端 继承实现方式

    和java后端代码一样 xff0c 前端j也有继承 xff0c 加js主要有以下几种继承方式 xff1a 对象冒充 xff0c call 方法 xff0c apply 方法 xff0c 原型链继承以及混合方式 lt DOCTYPE html
  • AI在情人节,限定数藏等你领!

    这个情人节 xff0c 百度超级链为您准备了一份不一样的礼物 xff01 我们选择了全球以 浪漫 闻名的城市 xff0c 参考梵高 高更 毕加索 克里姆特 蒙德里安等知名艺术家的风格 xff0c 借助百度文心大模型创作一系列 情人节 主题艺
  • nvm 切换node 版本显示成功,但是查看还一直是之前的

    这个问题纠结了好久 xff0c 应该是先装的node xff0c 后面再装nvm引起的 xff0c 网上试了各种方法都不行 xff0c 后面发现直接在环境变量里面改可以切换了
  • 树莓派3B+ 安装系统

    树莓派3B 43 安装系统 对于树莓派3B 43 系统安装方法有很多 xff0c 我就介绍比较普通的一种 适合小白操作 xff01 安装概要步骤 xff1a 官网下载系统 刷入TF卡 设置开启显示器和SSH 通电 进入系统 1 进入官方网站
  • SSIS之“查找” 组件(功能解释 细节 图文 数据讲解)

    对比源数据和目标数据 xff0c 对设定查找条件进行查找 xff0c 相同查找条件的数据放一堆 xff0c 不同的放另一堆 今天我通过一个简单的例子来讲解 xff1a 从一个新的逗号分隔符格式的TXT文件里的数据 xff0c 通过查找组件
  • VNCserver服务配置

    VNCserver服务配置 xff08 麒麟版 xff09 vncserver是linux系统进行终端登录较为好用的一款软件 xff0c 但在某些情况下 xff0c 我们登录到vnc终端时 xff0c 发现出现界面不显示 xff0c 只有命
  • 云服务器 VNC 远程连接

    此服务器买来是为了搭建IC EDA云的 xff0c 因此选用的是centOS 6的环境 xff0c 对各EDA软件兼容较好 本人手头拮据 xff0c 因此买的是腾讯云活动期间的云服务器 xff0c 只能说够用吧 一 桌面安装 在云服务器控制
  • 解决VNC中Linux系统与Win系统中复制粘贴问题!(亲测有效!)

    解决VNC中Linux系统与Win系统中复制粘贴问题 1 这是我的VNC viewer的版本号 然后我想实现VNC与win系统的复制粘贴 2 解决方式 第一步 我在VNC中的Linux桌面打开终端 输入 vncconfig 然后 enter
  • 常见非关系型数据库(NoSQL)推荐介绍

    目录 非关系型数据库的特点 1 关系型数据库 2 关系型数据库瓶颈 3 NoSQL
  • 各种好用的在线时钟、网页时钟汇总推荐集合

    电脑全屏时钟网页版 https www sioe cn rili quanpingshizhong php 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61
  • Caused by: libcore.io.ErrnoException: open failed: ENOENT (No such file or d.......

    problem reading network stats Caused by libcore io ErrnoException open failed ENOENT No such file or d 我出现此错误是由于activity
  • MapReduce实现分词和倒排索引(算法TF-IDF)

    MapReduce实现分词和倒排索引 算法TF IDF 介绍IFDF IF xff1a 词频 xff08 单词在文档中出现的次数 文档中的总词数 xff09 DF xff1a 逆向文件频率 xff08 log 文档总数 出现该单词的文件数量
  • 节点共建,来了!

    节点是分布式区块链网络公信力的重要来源 百度超级链开放网络 xff08 XuperOS xff09 自2020年上线以来 xff0c 一直秉承透明可信 开放共享的理念对外招募超级节点 XuperOS最终有25个超级节点 xff0c 这些分布
  • 线程池简单案例

    线程池使用案例 一 Executors1 newFixedThreadPool2 newCachedThreadPool3 newSingleThreadExecutor4 newScheduledThreadPool二 ThreadPoo