JUC-线程Callable使用与FutureTask源码阅读

news2024/11/24 22:38:47

JUC-线程Callable使用与FutureTask源码阅读

Callable简单使用

带返回值的线程(实现implements Callable<返回值类型>),使用示例

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import java.util.concurrent.RunnableFuture;

/**

- 实现Callable<T> 接口

- 含返回值且可抛出异常的线程创建启动方式

- @author fatah
  */
  public class Demo5 implements Callable<String>{

  public String call() throws Exception {
      System.out.println("正在执行新建线程任务");
      Thread.sleep(2000);
      return "新建线程睡了2s后返回执行结果";
  }

  public static void main(String[] args) throws InterruptedException, ExecutionException {
      Demo5 d = new Demo5();
      /*    call()只是线程任务,对线程任务进行封装
          class FutureTask<V> implements RunnableFuture<V>
          interface RunnableFuture<V> extends Runnable, Future<V>
      */
      FutureTask<String> task = new FutureTask<>(d);
      Thread t = new Thread(task);
      t.start();
      System.out.println("提前完成任务...");
      //获取任务执行后返回的结果
      String result = task.get();
      System.out.println("线程执行结果为"+result);
  }

}

FutureTask面向对象方式学习

为了定义这样一个事物“有返回结果”,暂且称之为RunnableFuture。它集合了Runnable和Future两种事物

(其中Future接口 表示了一个任务的生命周期,是一个可取消的异步运算,可以把它看作是一个异步操作的结果的占位符,它将在未来的某个时刻完成,并提供对其结果的访问。在并发包中许多异步任务类都继承自Future)

在这里插入图片描述

其中

  • Future接口主要使用get()方法获取线程任务返回值

  • Runnable接口的run()方法是执行线程任务主体

public interface Runnable {
    public abstract void run();
}


public interface Future<V> {
	//取消任务
    boolean cancel(boolean mayInterruptIfRunning);
 
    boolean isCancelled();
    
    //任务是否完成
    boolean isDone();
    
    // 获取任务完成情况
    V get() throws InterruptedException, ExecutionException;
 
    V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}




public interface RunnableFuture<V> extends Runnable, Future<V> {
    void run();
}


结合两个接口创造出RunnableFuture接口

FutureTask构造方法

当使用new FutureTask()构造对象时,需要Callable接口类。如果是Runnable接口,使用适配器转换为Callable类型对象。*

  • FutureTask(Callable callable)
public FutureTask(Callable<V> callable) {
    if (callable == null)
        throw new NullPointerException();
    this.callable = callable;
    this.state = NEW;       // ensure visibility of callable
}
  • FutureTask(Runnable runnable, V result)

此处使用了适配器模式,通过工具方法Executors.callable方法把Runnable转化为Callable调用

public FutureTask(Runnable runnable, V result) {
    this.callable = Executors.callable(runnable, result);
    this.state = NEW;       // ensure visibility of callable
}

Executors.java中

    public static <T> Callable<T> callable(Runnable task, T result) {
        if (task == null)
            throw new NullPointerException();
        return new RunnableAdapter<T>(task, result);
    }

    /**
     * 运行给定任务并返回给定结果的可调用对象
     */
    static final class RunnableAdapter<T> implements Callable<T> {
        final Runnable task;
        final T result;
        RunnableAdapter(Runnable task, T result) {
            this.task = task;
            this.result = result;
        }
        public T call() {
            task.run();
            return result;
        }
    }

其中callable是FutureTask内部私有变量

    private Callable<V> callable;

Run方法-RunnableFuture接口实现的

Callable c = callable;

result = c.call();

1.此处调用函数式接口Callable业务**call()**方法

    public void run() {
        if (state != NEW ||
            !UNSAFE.compareAndSwapObject(this, runnerOffset,
                                         null, Thread.currentThread()))
            return;
        try {
            Callable<V> c = callable;
            if (c != null && state == NEW) {
                V result;
                boolean ran;
                try {
                    result = c.call();1.重点!!!)
                    ran = true;
                } catch (Throwable ex) {
                    result = null;
                    ran = false;
                    setException(ex);
                }
                if (ran)
                    set(result);2.重点!!!)
            }
        } finally {
            // runner must be non-null until state is settled to
            // prevent concurrent calls to run()
            runner = null;
            // state must be re-read after nulling runner to prevent
            // leaked interrupts
            int s = state;
            if (s >= INTERRUPTING)
                handlePossibleCancellationInterrupt(s);
        }
    }

运行任务,如果任务状态为NEW状态,则利用CAS修改为当前线程。

2.业务任务执行完毕调用set(result)方法设置执行结果。set(result)源码如下:

其中outcome为FutureTask私有变量

private Object outcome;
    protected void set(V v) {
        if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
            outcome = v;
            UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final state
            finishCompletion();
        }
    }

Get()方法-Future接口实现

    public V get() throws InterruptedException, ExecutionException {
        int s = state;
        if (s <= COMPLETING)
            s = awaitDone(false, 0L);
        return report(s);
    }

说明:FutureTask 通过get()方法获取任务执行结果。如果任务处于未完成的状态(state <= COMPLETING),就调用awaitDone方法(后面单独讲解)等待任务完成。任务完成后,通过report方法获取执行结果或抛出执行期间的异常。report源码如下。

    private V report(int s) throws ExecutionException {
        Object x = outcome;
        if (s == NORMAL)
            return (V)x;
        if (s >= CANCELLED)
            throw new CancellationException();
        throw new ExecutionException((Throwable)x);
    }

可以看到使用get()方法会调用awaitDone等待线程完成,同时响应线程“取消”等操作。

可以看到report中 return (V)x; 即run方法中存储线程任务执行返回结果outcome

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/518617.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

STC32G12K128单片机的 moubus-rtu 主机测试工程

简介 STC32G12K128 是STC 推出的一款32位的 C251 的单片机。最近拿到一块官方申请的 屠龙刀-STC32G开发板&#xff0c;就用它的提供的库函数&#xff0c;查考安富莱提供的 modbus 例程移植了一个 modbus-rtu 主站的工程。 modbus-rtu host 移植注意点 modbus-rtu 功能配置 …

MapReduce序列化【用户流量使用统计】

目录 什么是序列化和反序列化&#xff1f; 序列化 反序列化 为什么要序列化&#xff1f; 序列化的主要应用场景 MapReduce实现序列化 自定义bean对象实现Writable接口 1.实现Writable接口 2.无参构造 3.重写序列化方法 4.重写反序列化方法 5.顺序一致 6.重写toStri…

您应该查看的5个ChatGPT WordPress插件

要创建免费网站&#xff1f;从易服客建站平台免费开始 500M免费空间&#xff0c;可升级为20GB电子商务网站 您应该查看的5个ChatGPT WordPress插件 发布于 2023年4月1日 ChatGPT 席卷了数字世界。作为内容创建者或营销者&#xff0c;您可能希望通过在您的网站上使用ChatGPT…

JimuReport - 积木报表(一款免费Web报表工具)

一款免费的数据可视化报表&#xff0c;含报表和大屏设计&#xff0c;像搭建积木一样在线设计报表&#xff01;功能涵盖&#xff0c;数据报表、打印设计、图表报表、大屏设计等&#xff01; Web 版报表设计器&#xff0c;类似于excel操作风格&#xff0c;通过拖拽完成报表设计。…

扫雷【C语言】

用C语言实现一个9X9的扫雷 test.c 测试部分 game.c 游戏实现部分 game.h 游戏声明部分 菜单部分 游戏部分 游戏部分包括创建一个扫雷的区域&#xff0c;在其中埋雷&#xff0c;玩家进行扫雷&#xff0c;判断扫雷是否成功 这里我i们定义行列&#xff0c;便于以后将其…

2023.05.12-使用Transformers Agents来一键调用千万个AI模型

1. 简介 简单来说&#xff0c;就是以前想要实现某一个AI功能&#xff0c;需要自己去网上搜索对应的模型、下载对应的权重才能使用。现在可以把中间的这些个环节都砍了&#xff0c;我们只需要告诉模型我们想要对某段文字或者某张图片进行什么操作&#xff0c;transformer就会自…

【经验贴】项目风险管理的有效方法

你遇见过“最奇葩”的项目风险是什么&#xff1f; 中级项目经理小李&#xff1a;我比较幸运? 项目一开始发现客户的需求不太明确&#xff0c;就识别出可能会有范围无限蔓延的风险&#xff0c;制定了一系列的应对措施&#xff0c;不出所料出了问题&#xff0c;最终还是将风险遏…

springboot整合redis,MongoDB,Elasticsearch(ES)

目录 springboot整合redis 连接Redis 字符串操作 哈希表操作 列表操作 集合操作 有序集合操作 lettcus与jedis的区别 springboot整合MongoDB 新增数据 查询数据 更新数据 删除数据 springboot整合Elasticsearch&#xff08;ES&#xff09; 创建ElasticsearchRepo…

区间预测 | MATLAB实现QRCNN-BiLSTM卷积双向长短期记忆神经网络分位数回归时间序列区间预测

区间预测 | MATLAB实现QRCNN-BiLSTM卷积双向长短期记忆神经网络分位数回归时间序列区间预测 目录 区间预测 | MATLAB实现QRCNN-BiLSTM卷积双向长短期记忆神经网络分位数回归时间序列区间预测效果一览基本介绍模型描述程序设计参考资料 效果一览 基本介绍 1.Matlab实现基于QRCNN…

Redis数据热迁移

1、redis数据热迁移&#xff0c;先通过redis-shake工具实现。 2、再通过redis-full-check检查迁移后的数据是否想同。 3、redis-shake版本下载&#xff1a; https://github.com/tair-opensource/RedisShake/releases 4、redis-full-check版本下载&#xff1a; https://github.c…

更简单的存和取bean

注解&#xff08;更简单存bean和取bean&#xff09;更简单的存bean&#xff08;使用类注解&#xff09;方法注解更简单的获取bean 注解&#xff08;更简单存bean和取bean&#xff09; 注解&#xff1a;声明和表示这个类或方法有某个能力。servlet的Web注解&#xff1b;实现路由…

2000多套微信小程序源码-史上最全的不同行业的源码集合

前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 很多伙伴学习小程序不知怎么开始&#xff0c;我准备了2000多套小程序源码&#xff0c;基本覆盖各个行业&#xff0c;大家有需要的可以借鉴学习~ 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面…

“数字人交互,与虚拟的自己互动”——用PaddleAvatar打造数字分身,探索人机交互的未来

“数字人交互&#xff0c;与虚拟的自己互动”——用PaddleAvatar打造数字分身&#xff0c;探索人机交互的未来 你是否曾经幻想过与自己的虚拟人交互&#xff1f;现在&#xff0c;使用PaddleAvatar&#xff0c;您可以将自己的图像、音频和视频转化为一个逼真的数字人视频&#…

Spring Cloud Alibaba--Nacos集群配置

文章目录 一、Nacos持久化配置二、Nacos集群配置三、避坑指南集群端口号冲突问题内存不足&#xff0c;无法启动的问题 一、Nacos持久化配置 Nacos默认自带的是嵌入式数据库derby&#xff0c;Nacos采用了集中式存储的方式来支持集群化部署&#xff0c;目前只支持MySQL的存储。 …

Goby 漏洞更新 |secnet-智能路由系统 actpt_5g.data 信息泄露

漏洞名称&#xff1a;secnet-智能路由系统 actpt_5g.data 信息泄露 English Name&#xff1a;secnet Intelligent Router actpt_5g.data Infoleakage CVSS core: 7.5 影响资产数&#xff1a;71768 漏洞描述&#xff1a; secnet安网智能AC管理系统是广州安网通信技术有限公…

mysql错误:2059 - Authentication plugin ‘caching_ sha2_password‘ cannot be loaded:

这个错误是因为MySQL数据库使用了 caching_sha2_password 插件进行身份验证&#xff0c;而该插件需要 MySQL 8.0.4 及以上版本的 MySQL 客户端才能够使用。 如果你使用的是旧版本的 MySQL 客户端&#xff0c;可以考虑升级到 MySQL 8.0.4 或更高版本。如果升级不是一个可行的选…

Windows重启mysql的方法(快速简单)

目录 一、背景 二、操作步骤 错误做法 正确做法 一、背景 有时候修改了数据库&#xff0c;但是MySQL数据库内容有延迟缓存&#xff0c;那么就需要重启一下数据库去解决问题 二、操作步骤 错误做法 直接去cmd命令里面输入net stop mysql这样停止&#xff0c;这样很可能…

【C++初阶】C++模版(进阶)

文章目录 前言一、非类型模板参数二、模板的特化概念函数模板特化类模板特化1.全特化3.偏特化 三、模板分离编译什么是分离编译模板的分离编译解决方法 模板总结 前言 前边我们讲解了模版初阶的内容&#xff0c;对泛型编程&#xff0c;函数模版&#xff0c;类模板有了一定的认…

上海亚商投顾:沪指失守3300点关口 AI应用方向大幅调整

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 市场情绪 三大指数今日集体调整&#xff0c;尾盘均跌超1%&#xff0c;沪指失守3300点关口&#xff0c;日线录得4连阴走势。游…

IS210AEPSG1AFC磁场由串联励磁绕组和并联励磁的组合提供

​ IS210AEPSG1AFC磁场由串联励磁绕组和并联励磁的组合提供 复合发生器 在这种类型中&#xff0c;磁场由串联励磁绕组和并联励磁的组合提供&#xff0c;并联磁场有许多圈数的导线&#xff0c;但它只承载小电流&#xff0c;而串联励磁绕组有几圈粗线并承载负载电流 串联励磁绕组…