FutureTask的用法及两种经常使用的使用场景

2023-05-16

FutureTask可用于异步获取执行结果或取消执行任务的场景。经过传入Runnable或者Callable的任务给FutureTask,直接调用其run方法或者放入线程池执行,以后能够在外部经过FutureTask的get方法异步获取执行结果,所以,FutureTask很是适合用于耗时的计算,主线程能够在完成本身的任务后,再去获取结果。另外,FutureTask还能够确保即便调用了屡次run方法,它都只会执行一次Runnable或者Callable任务,或者经过cancel取消FutureTask的执行等。java

1.执行多任务计算
FutureTask执行多任务计算的使用场景安全

利用FutureTask和ExecutorService,能够用多线程的方式提交计算任务,主线程继续执行其余任务,当主线程须要子线程的计算结果时,在异步获取子线程的执行结果。多线程

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

public class FutureTaskForMultiCompute {

public static void main(String[] args) {

    FutureTaskForMultiCompute inst = new FutureTaskForMultiCompute();
    // 建立任务集合
    List<FutureTask<Integer>> taskList = new ArrayList<FutureTask<Integer>>();
    // 建立线程池
    ExecutorService exec = Executors.newFixedThreadPool(5);
    for (int i = 0; i < 10; i++) {
        // 传入Callable对象建立FutureTask对象
        FutureTask<Integer> ft = new FutureTask<Integer>(inst.new ComputeTask(i, "" + i));
        taskList.add(ft);
        // 提交给线程池执行任务,也能够经过exec.invokeAll(taskList)一次性提交全部任务;
        exec.submit(ft);
    }

    System.out.println("全部计算任务提交完毕, 主线程接着干其余事情!");

    // 开始统计各计算线程计算结果
    Integer totalResult = 0;
    for (FutureTask<Integer> ft : taskList) {
        try {
            //FutureTask的get方法会自动阻塞,直到获取计算结果为止
            totalResult = totalResult + ft.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }

    // 关闭线程池
    exec.shutdown();
    System.out.println("多任务计算后的总结果是:" + totalResult);

}

private class ComputeTask implements Callable<Integer> {

    private Integer result = 0;
    private String taskName = "";

    public ComputeTask(Integer iniResult, String taskName) {
        result = iniResult;
        this.taskName = taskName;
        System.out.println("生成子线程计算任务: " + taskName);
    }

    public String getTaskName() {
        return this.taskName;
    }

    @Override
    public Integer call() throws Exception {
        // TODO Auto-generated method stub

        for (int i = 0; i < 100; i++) {
            result = +i;
        }
        // 休眠5秒钟,观察主线程行为,预期的结果是主线程会继续执行,到要取得FutureTask的结果是等待直至完成。
        Thread.sleep(5000);
        System.out.println("子线程计算任务: " + taskName + " 执行完成!");
        return result;
    }
}

}
生成子线程计算任务: 0
生成子线程计算任务: 1
生成子线程计算任务: 2
生成子线程计算任务: 3
生成子线程计算任务: 4
生成子线程计算任务: 5
生成子线程计算任务: 6
生成子线程计算任务: 7
生成子线程计算任务: 8
生成子线程计算任务: 9
全部计算任务提交完毕, 主线程接着干其余事情!
子线程计算任务: 0 执行完成!
子线程计算任务: 2 执行完成!
子线程计算任务: 3 执行完成!
子线程计算任务: 4 执行完成!
子线程计算任务: 1 执行完成!
子线程计算任务: 8 执行完成!
子线程计算任务: 7 执行完成!
子线程计算任务: 6 执行完成!
子线程计算任务: 9 执行完成!
子线程计算任务: 5 执行完成!
多任务计算后的总结果是:990

2.高并发环境下
FutureTask在高并发环境下确保任务只执行一次并发

在不少高并发的环境下,每每咱们只须要某些任务只执行一次。这种使用情景FutureTask的特性恰能胜任。举一个例子,假设有一个带key的链接池,当key存在时,即直接返回key对应的对象;当key不存在时,则建立链接。对于这样的应用场景,一般采用的方法为使用一个Map对象来存储key和链接池对应的对应关系,典型的代码以下面所示:异步

private Map<String, Connection> connectionPool = new HashMap<String, Connection>();
private ReentrantLock lock = new ReentrantLock();

public Connection getConnection(String key) {
    try {
        lock.lock();
        if (connectionPool.containsKey(key)) {
            return connectionPool.get(key);
        } else {
            //建立 Connection  
            Connection conn = createConnection();
            connectionPool.put(key, conn);
            return conn;
        }
    } finally {
        lock.unlock();
    }
}

//建立Connection  
private Connection createConnection() {
    return null;
}

在上面的例子中,咱们经过加锁确保高并发环境下的线程安全,也确保了connection只建立一次,然而确牺牲了性能。改用ConcurrentHash的状况下,几乎能够避免加锁的操做,性能大大提升,可是在高并发的状况下有可能出现Connection被建立屡次的现象。这时最须要解决的问题就是当key不存在时,建立Connection的动做能放在connectionPool以后执行,这正是FutureTask发挥做用的时机,基于ConcurrentHashMap和FutureTask的改造代码以下:ide

private ConcurrentHashMap<String, FutureTask> connectionPool = new ConcurrentHashMap<String, FutureTask>();

public Connection getConnection(String key) throws Exception {
    FutureTask<Connection> connectionTask = connectionPool.get(key);
    if (connectionTask != null) {
        return connectionTask.get();
    } else {
        Callable<Connection> callable = new Callable<Connection>() {
            @Override
            public Connection call() throws Exception {
                // TODO Auto-generated method stub  
                return createConnection();
            }
        };
        FutureTask<Connection> newTask = new FutureTask<Connection>(callable);
        connectionTask = connectionPool.putIfAbsent(key, newTask);
        if (connectionTask == null) {
            connectionTask = newTask;
            connectionTask.run();
        }
        return connectionTask.get();
    }
}

//建立Connection  
private Connection createConnection() {
    return null;
}

通过这样的改造,能够避免因为并发带来的屡次建立链接及锁的出现。高并发

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

FutureTask的用法及两种经常使用的使用场景 的相关文章

  • vue-进入/离开&列表过渡

    vue 进入 离开 amp 列表过渡 在 CSS 过渡和动画中自动应用 class可以配合使用第三方 CSS 动画库 xff0c 如 Animate css在过渡钩子函数中使用 JavaScript 直接操作 DOM可以配合使用第三方 Ja
  • vue中的路由基础

    vue中的路由 在使用vue router之前 xff0c 首先需要安装该插件 首先在cmd中使用npm install vue router进行插件的安装 xff0c 如果要在工程项目中使用它必须通过Vue use 明确地安装路由功能 就
  • 前端面试的基础四十小问(前20问)

    文章目录 1 什么是HTML语义化 xff1f 2 标签title与alt属性的区别是什么 xff1f 3 iframe的优缺点 xff1f 4 介绍一下CSS的盒子模型 xff1f 5 垂直居中的几种方式 xff1f 6 rgba和opa
  • 前端面试题--react与vue的区别

    前端面试题 react与vue的区别 首先从架构层面来看 xff0c vue是MVVM架构 xff0c 是一个灵活易用的渐进式双向绑定 xff0c 而react并没有准确的架构模式 xff0c react准确的架构模式是调和器和渲染器 xf
  • 前端面试题--详解flex

    前端面试题 详解flex Flex是指弹性盒子布局的意思 Flex的主要作用是 xff1a 解决元素居中问题 xff0c 自动弹性伸缩 xff0c 自动适配不同大小的屏幕和移动端 Flex的术语解释 xff1a 二成员 xff1a 容器和项
  • Linux系统中sysctl命令详解 sysctl -p、sysctl -a、sysctl -w

    sysctl命令用于运行时配置内核参数 xff0c 这些参数位于 proc sys目录下 sysctl配置与显示在 proc sys目录中的内核参数 xff0e 可以用sysctl来设置或重新设置联网功能 xff0c 如IP转发 IP碎片去
  • 前端面试题--vue的父子组件通信

    前端面试题 vue的父子组件通信 比较常见的就是父组件为控制组件子组件为视图组件 父组件传递数据给子组件使用 xff0c 遇到业务逻辑操作时子组件触发父组件的自定义事件 子组件接受使用父组件的数据 xff0c 这里的数据包括属性和方法 xf
  • 前端面试题--了解并简单介绍一下typescript

    前端面试题 了解并简单介绍一下typescript TypeScript是JavaScript的超集 xff0c 具有可选的类型并可以编译为纯JavaScript 从技术上讲TypeScript就是具有静态类型的 JavaScript 向J
  • HashMap MAXIMUM_CAPACITY 为什么设置成1 << 30---Java源码

    为什么是1 lt lt 30因为2个因素造成的 正如上楼的 MrAmity 所说 xff0c HashMap在确定数组下标Index的时候 xff0c 采用的是 length 1 amp hash的方式 xff0c 只有当length为2的
  • MATLAB循环结构与嵌套循环

    循环结构又称为重复结构 xff0c 是利用计算机运算速度快以及能进行逻辑控制得我特点来重复执行默写操作 while循环 while语句多用于循环次数不确定的情况 xff0c 而对于循环次数确定的情况 xff0c 使用for语句更方便 针对不
  • 机械臂(4)–正向求解

    最近准备研究下机械臂的运动分析 xff0c 本文记录相关过程 关于运动求解 xff0c 鄙人才疏学浅 xff0c 很多内容没有深入理解 xff0c 只是简单知道这个是什么 xff0c 代表什么意思 xff0c 怎么用 xff0c 关于原理了
  • Gazebo/Rviz仿真打开URDF模型

    当我们通过Solidworks成功导出URDF模型之后 xff0c 我们当然很希望在ROS中观察到自己导入的模型 ROS中有两个非常好的插件 xff0c 一个是RViz另一个是Gazebo 其中RViz类似一个可视化平台 xff0c 而Ga
  • 线性二次型最优控制

    本文涉及的李雅普诺夫方法的内容可参见另一篇博文 xff1a 李雅普诺夫 xff08 第二方法 xff09 稳定性分析 目录 一 连续时间系统线性二次型最优控制1 1 问题的提出1 2 问题的分析1 3 问题求解1 4 MATLAB函数1 5
  • 深入理解Tomcat虚拟目录

    我们知道 xff0c Web网站中的内容 xff08 包括网页 xff0c 图片 xff0c 音频文件等 xff09 一般都存放在App的目录下 但随着网站内容的不断丰富 xff0c 用户需要把不同层次的内容组织成网站的子目录 我们通常的做
  • Spring Security 实现身份认证

    Spring Security可以运行在不同的身份认证环境中 xff0c 当我们推荐用户使用Spring Security进行身份认证但并不推荐集成到容器管理的身份认证中时 xff0c 但当你集成到自己的身份认证系统时 xff0c 它依然是
  • 基于ubuntu18.04 VNC开机自启动

    本博客内容实现了RK3399 NanoPi NEO4的VNC的开机自启动 xff0c 以及原版桌面的显示 系统 xff1a FriendlyDesktop 最新版本 xff0d 基于Ubuntu 18 04 64位系统构建 易于开发 xff
  • Spring Security身份认证之UserDetailsService

    zhiqian我们采用了配置文件的方式从数据库中读取用户进行登录 虽然该方式的灵活性相较于静态账号密码的方式灵活了许多 xff0c 但是将数据库的结构暴露在明显的位置上 xff0c 绝对不是一个明智的做法 本文通过Java代码实现UserD
  • 基于Apache OLTU的OAuth2.0授权解决方案

    Apache OLTU实现了OAuth 2 0的规范 xff0c 是一种可靠的Java授权解决方案 但是 xff0c 官方文档实在是太惨不忍睹了 本文参考了开涛的 OAuth 2 0集成Shiro文章 模拟了OAuth2 0的认证流程 技术
  • Couch的MapReduce查询

    1 MapReduce介绍 传统的关系型数据库中 xff0c 只要你的数据是结构化的 xff0c 你可以进行任何类型的查询 Apache Couch与此相反 xff0c 它使用MapReduce xff08 预定义的map和的reduce方
  • Java遍历读取文件目录结构

    Java读取计算机目录 xff0c 并打印 public class ReadDirectory 文件所在的层数 private int fileLevel 生成输出格式 64 param name 输出的文件名或目录名 64 param

随机推荐

  • Java实现数字水印

    数字水印有可见不可见之分 xff0c 可见的比如课件上印有学校校徽 xff0c 微博发图片会水印上上传者的信息及微博logo等 用java实现可见的数字水印 xff0c 草人主要是用到了java awt包中的AlphaComposite类
  • 程序员应该如何去设计需求

    刚出道的程序员 xff0c 在做需求分析的时候 xff0c 总是经常挨批 xff0c 客户说他们不能按照客户的要求去设计原型 xff0c 领导说他们不用心去与客户沟通交流 程序员总是感到自己很冤枉 xff0c 明明客户没有给出一点建设性建议
  • 小小程序员的一周日报

    工作依旧在有条不紊的进行着 xff0c 一周的时间很快就会过去 xff0c 正如今天李哥所说的 xff0c 这一周还没有感觉怎么过呢 xff0c 就结束了 是啊 xff0c 这就是我们的工作 xff0c 程序员的工作 xff0c 软件设计师
  • 项目空间都有啥

    项目空间是什么 xff0c Workplace 答案是 xff1a No 项目空间是由项目负责人提出的实施某项目方案的一种流程 项目空间是XX海油ERP管理系统下的一个业务 xff0c 项目负责人通过创建项目名称 项目负责人 使用资源 所属
  • 你不要瞧不起Ctrl+C

    曾经 xff0c 在我未参加工作之前 xff0c 我认为靠 Ctrl 43 C 来完成工作的人 xff0c 肯定是懒惰的程序员 xff0c 但是现在我发现我错了 xff0c 而且是彻底的错了 能够通过 Ctrl 43 C 来完成工作的人 x
  • 文档交接说明书(模板)

    因为同事的离职 xff0c 我的入职 xff0c 要从同事手中交接过来一些项目 公司里只有一些开发文档相关的模板 xff0c 并没有文档交接相关的模板 xff0c 所以交接文档的模板也就由我们自己来定 我结合自己在工作中的经验 xff0c
  • UDS网络层/TP层(ISO 15765-2)的解读

    本文是对 ISO 15765 2 2011 协议的一些解读 需要指出该协议的最新版为2016版 TP层存在意义 UDS网络层 xff0c 又称为TP层 xff08 Transport Protocol Layer xff09 其存在的目的是
  • std vector传递指针使用说明

    今天用WM COPYDATA传递一个Vector的指针 xff0c 传递过来始终失败 后面找到一篇文章 xff0c 说只要传递第一个元素的地址就行 xff0c 因为vector在内存是连续的 static std vector lt UIm
  • Leetcode之运算库函数自定义

    一 Leetcode50 pow 注意点 1 n的值可以为正 xff0c 负 xff0c 0 2 O n 会TLE xff0c 使用递归时 xff0c 一定要将中间步保存 3 有博文中提到 xff0c 若n lt 0 xff0c 可以令n
  • 树莓派无键盘安装步骤

    树莓派无键盘安装 下载系统烧录系统配置无线网络开机并连接树莓派更新源和系统安装xrdp xff08 远程访问 xff09 Windows连接远程桌面 下载系统 应该只有官方的Raspbian系统支持无键盘安装 xff0c 官网下载系统 xf
  • iic实现采集温湿度传感器值

    iic h ifndef IIC H define IIC H include 34 stm32mp1xx gpio h 34 include 34 stm32mp1xx rcc h 34 通过程序模拟实现I2C总线的时序和协议 GPIOF
  • Matlab在线运行网站

    桌面版的Matlab不仅安装包很大 xff0c 而且也很吃性能 xff0c 不如就用网页版 xff0c 来玩啊 xff01 https www tutorialspoint com execute matlab online php 点击c
  • An Introduction on Deep Learning for the Physical Layer

    An Introduction on Deep Learning for the Physical Layer 代码实现 xff1a https github com shengjian3476077 DLforPhy 一 文章的主要工作
  • motion planning 一起学习

    shenlan 学院 motion planning 一起学习 打算买深蓝的motion planning for Mobile robots xff0c 主要是讲规划算法的 xff0c 有无一起学习的小伙伴 xff1f 一起学习 xff0
  • 【java面试之Linux】Linux启动过程、

    一 Linux启动过程 启动第一步 xff0d xff0d 加载BIOS 启动第二步 xff0d xff0d 读取MBR 主引导记录 启动第三步 xff0d xff0d Boot Loader 启动第四步 xff0d xff0d 加载内核
  • Linux SPI 驱动示例

    一 Linux 下 SPI 驱动框架 SPI 驱动框架分为主机控制器驱动和设备驱动 xff0c 主机控制器也就是 SOC 的 SPI 控制器接口 1 1 SPI 主机驱动 SPI 主机驱动就是 SOC 的 SPI 控制器驱动 xff0c L
  • 使用 FFmpeg 推流,使用 VLC 软件进行拉流

    1 移植Nginx到开发板 xff0c 使用 Nginx 来搭建 RTMP 流媒体服务器 2 执行如下命令进行推流 xff1a ffmpeg re i run media mmcblk1p1 testVideo mp4 c av copy
  • MPC与LQR的详细对比分析

    从以下几个方面进行阐述 xff1a 一 xff0c 研究对象 xff1a 是否线性 二 xff0c 状态方程 xff1a 离散化 三 xff0c 目标函数 xff1a 误差和控制量的极小值 四 xff0c 工作时域 xff1a 预测时域 x
  • 类类型成员引用的问题

    一个类中的成员变量是另一个类的类类型 xff0c 赋值问题分为引用 xff0c 不引用两类 如先定义TESTB类 class TESTB public TESTB b 61 3 7 TESTB void change b 61 9 0 fl
  • FutureTask的用法及两种经常使用的使用场景

    FutureTask可用于异步获取执行结果或取消执行任务的场景 经过传入Runnable或者Callable的任务给FutureTask xff0c 直接调用其run方法或者放入线程池执行 xff0c 以后能够在外部经过FutureTask