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

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 并发编程之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 功能,帮助创作者找到灵感,优化歌词结构,写出打动人心的作品。
|
2天前
|
安全 Ubuntu Shell
深入解析 vsftpd 2.3.4 的笑脸漏洞及其检测方法
本文详细解析了 vsftpd 2.3.4 版本中的“笑脸漏洞”,该漏洞允许攻击者通过特定用户名和密码触发后门,获取远程代码执行权限。文章提供了漏洞概述、影响范围及一个 Python 脚本,用于检测目标服务器是否受此漏洞影响。通过连接至目标服务器并尝试登录特定用户名,脚本能够判断服务器是否存在该漏洞,并给出相应的警告信息。
115 84
|
2月前
|
存储 算法 Java
解析HashSet的工作原理,揭示Set如何利用哈希算法和equals()方法确保元素唯一性,并通过示例代码展示了其“无重复”特性的具体应用
在Java中,Set接口以其独特的“无重复”特性脱颖而出。本文通过解析HashSet的工作原理,揭示Set如何利用哈希算法和equals()方法确保元素唯一性,并通过示例代码展示了其“无重复”特性的具体应用。
50 3
|
2月前
|
人工智能
写歌词的技巧和方法全解析:开启你的音乐创作之旅,妙笔生词智能写歌词软件
怀揣音乐梦想,渴望用歌词抒发情感?掌握关键技巧,你也能踏上创作之旅。灵感来自生活点滴,主题明确,语言简洁,韵律和谐。借助“妙笔生词智能写歌词软件”,AI辅助创作,轻松写出动人歌词,实现音乐梦想。
|
7天前
|
存储 监控 调度
云服务器成本优化深度解析与实战案例
本文深入探讨了云服务器成本优化的策略与实践,涵盖基本原则、具体策略及案例分析。基本原则包括以实际需求为导向、动态调整资源、成本控制为核心。具体策略涉及选择合适计费模式、优化资源配置、存储与网络配置、实施资源监控与审计、应用性能优化、利用优惠政策及考虑多云策略。文章还通过电商、制造企业和初创团队的实际案例,展示了云服务器成本优化的有效性,最后展望了未来的发展趋势,包括智能化优化、多云管理和绿色节能。
|
12天前
|
负载均衡 网络协议 算法
Docker容器环境中服务发现与负载均衡的技术与方法,涵盖环境变量、DNS、集中式服务发现系统等方式
本文探讨了Docker容器环境中服务发现与负载均衡的技术与方法,涵盖环境变量、DNS、集中式服务发现系统等方式,以及软件负载均衡器、云服务负载均衡、容器编排工具等实现手段,强调两者结合的重要性及面临挑战的应对措施。
34 3
|
1月前
|
JSON PHP 数据格式
PHP解析配置文件的常用方法
INI文件是最常见的配置文件格式之一。
46 12
|
1月前
|
存储 人工智能 自然语言处理
高效档案管理案例介绍:文档内容批量结构化解决方案解析
档案文件内容丰富多样,传统人工管理耗时低效。思通数科AI平台通过自动布局分析、段落与标题检测、表格结构识别、嵌套内容还原及元数据生成等功能,实现档案的高精度分块处理和结构化存储,大幅提升管理和检索效率。某历史档案馆通过该平台完成了500万页档案的数字化,信息检索效率提升60%。
|
1月前
|
机器学习/深度学习 人工智能 安全
TPAMI:安全强化学习方法、理论与应用综述,慕工大、同济、伯克利等深度解析
【10月更文挑战第27天】强化学习(RL)在实际应用中展现出巨大潜力,但其安全性问题日益凸显。为此,安全强化学习(SRL)应运而生。近日,来自慕尼黑工业大学、同济大学和加州大学伯克利分校的研究人员在《IEEE模式分析与机器智能汇刊》上发表了一篇综述论文,系统介绍了SRL的方法、理论和应用。SRL主要面临安全性定义模糊、探索与利用平衡以及鲁棒性与可靠性等挑战。研究人员提出了基于约束、基于风险和基于监督学习等多种方法来应对这些挑战。
59 2
|
1月前
|
Prometheus 监控 Cloud Native
实战经验:成功的DevOps实施案例解析
实战经验:成功的DevOps实施案例解析
51 6

推荐镜像

更多