并发编程之Callable方法的详细解析(带小案例)

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
简介: 并发编程之Callable方法的详细解析(带小案例)

Callable

(第三种线程实现方式)

Callable与Runnable的区别

Callable与Runnable的区别

  1. 实现方法名称不一样
  2. 有返回值
  3. 抛出了异常



class Thread1 implements Runnable{
    @Override
    public void run() {
    }
}
class Thread2 implements Callable<Integer>{
    //1.方法名称不一样  2.有返回值  3.抛出了异常
    @Override
    public Integer call() throws Exception {
        return null;
    }
}

Callable的使用

Callable线程类的运行,需要依靠FutureTask的封装,因为Thread类的构造方法只支持Runnable及其子类,于是就需要继承了Runnable的FutureTast来对Callable子类进行封装,下面是FurtureTast的继承关系源代码:

public class FutureTask<V> implements RunnableFuture<V> {

public interface RunnableFuture<V> extends Runnable, Future<V> {

public class CallableDemo {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        FutureTask<Integer> futureTask = new FutureTask<>(new Thread2());
        new Thread(futureTask).start();
        System.out.println(futureTask.get());
    }
}
class Thread2 implements Callable<Integer>{
    //1.方法名称不一样  2.有返回值  3.抛出了异常
    @Override
    public Integer call() throws Exception {
        System.out.println("come in");
        return 1024;
    }
}

Callable的细节

使用callable就相当于另外开了一条线程运行,调用get方法就相当于要获取这条线程的运行结果。

如果在mian线程中调用了get方法,就会阻塞起来等待这个线程的运行结果。

于是就出现如下情况:

demo1

运行结果:

代码:

public class CallableDemo {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        FutureTask<Integer> futureTask = new FutureTask<>(new Thread2());
        new Thread(futureTask).start();
        System.out.println("main");
        System.out.println(futureTask.get()); //后调用get方法
    }
}
class Thread2 implements Callable<Integer>{
    //1.方法名称不一样  2.有返回值  3.抛出了异常
    @Override
    public Integer call() throws Exception {
        Thread.sleep(2000);
        System.out.println("come in");
        return 1024;
    }
}
demo2

运行结果:

代码:

public class CallableDemo {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        FutureTask<Integer> futureTask = new FutureTask<>(new Thread2());
        new Thread(futureTask).start();
        System.out.println(futureTask.get()); //先调用get方法,会在这里等待线程返回结果
        System.out.println("main");
    }
}
class Thread2 implements Callable<Integer>{
    //1.方法名称不一样  2.有返回值  3.抛出了异常
    @Override
    public Integer call() throws Exception {
        Thread.sleep(2000);
        System.out.println("come in");
        return 1024;
    }
}

Callable的细节2

callable多次运行,只会计算一次结果

运行结果:(可以看到 只执行了一次come in的输出,即call()这个方法的代码只运行了一次)

代码:



public class CallableDemo2 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        FutureTask<Integer> futureTask = new FutureTask<>(new Thread3());
        Thread t1 = new Thread(futureTask);  //第一次调用 这个 futruetask任务
        t1.start();
        Thread t2 = new Thread(futureTask);  //第二次调用 这个 futruetask任务
        t2.start();
        System.out.println(futureTask.get());
        System.out.println(futureTask.get());
        System.out.println("main");
    }
}
class Thread3 implements Callable<Integer>{
    private static int num = 0;
    //1.方法名称不一样  2.有返回值  3.抛出了异常
    @Override
    public Integer call() throws Exception {
        System.out.println("come in");
        return ++num;
    }
}

原生Thread多次执行start会抛出IllegalThreadStateException非法的线程状态异常,Callable也是一样

Thread的start() 源码:

public synchronized void start() {
     /**
         * This method is not invoked for the main method thread or "system"
         * group threads created/set up by the VM. Any new functionality added
         * to this method in the future may have to also be added to the VM.
         *
         * A zero status value corresponds to state "NEW".
         */
        if (threadStatus != 0)
            throw new IllegalThreadStateException();  //如果线程已经启动,则抛出异常
        /* Notify the group that this thread is about to be started
         * so that it can be added to the group's list of threads
         * and the group's unstarted count can be decremented. */
        group.add(this);
        boolean started = false;
        try {
            start0();
            started = true;
        } finally {
            try {
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
                /* do nothing. If start0 threw a Throwable then
                  it will be passed up the call stack */
            }
        }
    }


相关文章
|
2月前
|
人工智能
歌词结构的巧妙安排:写歌词的方法与技巧解析,妙笔生词AI智能写歌词软件
歌词创作是一门艺术,关键在于巧妙的结构安排。开头需迅速吸引听众,主体部分要坚实且富有逻辑,结尾则应留下深刻印象。《妙笔生词智能写歌词软件》提供多种 AI 功能,帮助创作者找到灵感,优化歌词结构,写出打动人心的作品。
|
4天前
|
NoSQL Java Linux
《docker高级篇(大厂进阶):2.DockerFile解析》包括:是什么、DockerFile构建过程解析、DockerFile常用保留字指令、案例、小总结
《docker高级篇(大厂进阶):2.DockerFile解析》包括:是什么、DockerFile构建过程解析、DockerFile常用保留字指令、案例、小总结
132 75
|
16天前
|
安全 Ubuntu Shell
深入解析 vsftpd 2.3.4 的笑脸漏洞及其检测方法
本文详细解析了 vsftpd 2.3.4 版本中的“笑脸漏洞”,该漏洞允许攻击者通过特定用户名和密码触发后门,获取远程代码执行权限。文章提供了漏洞概述、影响范围及一个 Python 脚本,用于检测目标服务器是否受此漏洞影响。通过连接至目标服务器并尝试登录特定用户名,脚本能够判断服务器是否存在该漏洞,并给出相应的警告信息。
133 84
|
3天前
|
存储 设计模式 算法
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,它涉及算法与对象间职责的分配。行为型模式分为类行为模式和对象行为模式,前者采用继承机制来在类间分派行为,后者采用组合或聚合在对象间分配行为。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象行为模式比类行为模式具有更大的灵活性。 行为型模式分为: • 模板方法模式 • 策略模式 • 命令模式 • 职责链模式 • 状态模式 • 观察者模式 • 中介者模式 • 迭代器模式 • 访问者模式 • 备忘录模式 • 解释器模式
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
|
15天前
|
存储 Java 开发者
浅析JVM方法解析、创建和链接
上一篇文章《你知道Java类是如何被加载的吗?》分析了HotSpot是如何加载Java类的,本文再来分析下Hotspot又是如何解析、创建和链接类方法的。
|
22天前
|
存储 监控 调度
云服务器成本优化深度解析与实战案例
本文深入探讨了云服务器成本优化的策略与实践,涵盖基本原则、具体策略及案例分析。基本原则包括以实际需求为导向、动态调整资源、成本控制为核心。具体策略涉及选择合适计费模式、优化资源配置、存储与网络配置、实施资源监控与审计、应用性能优化、利用优惠政策及考虑多云策略。文章还通过电商、制造企业和初创团队的实际案例,展示了云服务器成本优化的有效性,最后展望了未来的发展趋势,包括智能化优化、多云管理和绿色节能。
|
27天前
|
负载均衡 网络协议 算法
Docker容器环境中服务发现与负载均衡的技术与方法,涵盖环境变量、DNS、集中式服务发现系统等方式
本文探讨了Docker容器环境中服务发现与负载均衡的技术与方法,涵盖环境变量、DNS、集中式服务发现系统等方式,以及软件负载均衡器、云服务负载均衡、容器编排工具等实现手段,强调两者结合的重要性及面临挑战的应对措施。
63 3
|
1月前
|
JSON PHP 数据格式
PHP解析配置文件的常用方法
INI文件是最常见的配置文件格式之一。
54 12
|
1月前
|
存储 人工智能 自然语言处理
高效档案管理案例介绍:文档内容批量结构化解决方案解析
档案文件内容丰富多样,传统人工管理耗时低效。思通数科AI平台通过自动布局分析、段落与标题检测、表格结构识别、嵌套内容还原及元数据生成等功能,实现档案的高精度分块处理和结构化存储,大幅提升管理和检索效率。某历史档案馆通过该平台完成了500万页档案的数字化,信息检索效率提升60%。
|
1月前
|
机器学习/深度学习 人工智能 安全
TPAMI:安全强化学习方法、理论与应用综述,慕工大、同济、伯克利等深度解析
【10月更文挑战第27天】强化学习(RL)在实际应用中展现出巨大潜力,但其安全性问题日益凸显。为此,安全强化学习(SRL)应运而生。近日,来自慕尼黑工业大学、同济大学和加州大学伯克利分校的研究人员在《IEEE模式分析与机器智能汇刊》上发表了一篇综述论文,系统介绍了SRL的方法、理论和应用。SRL主要面临安全性定义模糊、探索与利用平衡以及鲁棒性与可靠性等挑战。研究人员提出了基于约束、基于风险和基于监督学习等多种方法来应对这些挑战。
72 2

推荐镜像

更多