使用Runnable和Callable接口实现多线程的区别

先看两种实现方式的步骤:

1.实现Runnable接口

public class ThreadDemo{
public static void main(String[] args) {
for (int i = 1; i <= 5; i++) {
//创建并启动由实现Runnable接口创建的线程
new Thread(new Runner(),"Thread"+i).start();
}
}
} //实现Runnable接口
class Runner implements Runnable{
//实现run方法
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"有实现Runnable接口创建");
}
}

2.实现 Callable 接口

public class ThreadDemo{
public static void main(String[] args) throws ExecutionException, InterruptedException {
for (int i = 1; i <= 5; i++) {
//使用FutureTask保存线程结果
FutureTask<String> futureTask = new FutureTask<String>(new Caller());
//创建并启动由实现Callable创建的线程
new Thread(futureTask,"Thread"+i).start();
//获取线程执行结果
System.out.println(futureTask.get());
}
}
} //实现Callable接口
class Caller implements Callable{
//实现Call接口
@Override
public Object call() throws Exception {
String result = Thread.currentThread().getName()+"由实现Callable接口创建";
return result;
}
}

从以上代码可以看出,使用 Callable 接口创建多线程时使用了 FutureTask 进行封装,然后 FutureTask 作为参数传给 Thread 的构造函数,而 FutureTask 的作用是存放 Callable 接口 call 方法的返回值。我们来看一下 FutureTask 的源码

//FutureTask实现了RunnableFuture接口
public class FutureTask<V> implements RunnableFuture<V> {} //再看RunnableFuture接口,继承了Runnable接口
public interface RunnableFuture<V> extends Runnable, Future<V> {
void run();
} //回到FutureTask,找到run方法
public void run() {
...
Callable<V> c = callable;
if (c != null && state == NEW) {
V result;
boolean ran;
try {
//获取call的返回值
result = c.call();
ran = true;
} catch (Throwable ex) {
result = null;
ran = false;
setException(ex);
}
if (ran)
set(result);
}
...
} //看一下set方法
protected void set(V v) {
if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
outcome = v;
...
}
} //再看一下FutureTask的构造函数
public FutureTask(Callable<V> callable) {
if (callable == null)
throw new NullPointerException();
this.callable = callable;
this.state = NEW;
}

从对 FutureTask 的源码分析,我们可以看出 FutureTask 实现了 Runnable 接口的 run 方法,在 run 方法中调用了 Callable 的 call 方法,将结果保存到 result 中,通过 set 方法将结果存储至 outcome 变量中。

通过以上分析,我们总结出使用 Runnable 和 Callable 接口的区别:

  1. 使用 Runnable 接口实现更加简单,而 通过 Callable 接口创建线程需要 FutureTask 进行封装;
  2. 通过实现 Runnable 接口创建的线程没有返回值,而使用 Callable 接口创建的线程可以有返回结果,并保存在 FutureTask中;
  3. 通过实现 Runnable 接口创建线程不抛出异常,而使用 Callable 接口创建的线程会抛出异常;

从以上总结可以看出,我们也可以看出 Runnable 适用于无需返回值的场景,而 Callable 接口用于需要保存返回值的场景。

使用Runnable和Callable接口实现多线程的区别的更多相关文章

  1. 使用Thread类和Runnable接口实现多线程的区别

    使用Thread类和Runnable接口实现多线程的区别 先看两种实现方式的步骤: public class ThreadDemo{ public static void main(String[] ...

  2. 通过Callable接口实现多线程

    一.通过Callable接口实现多线程 c.实现Callable重写call方法 实现Callable和实现Runnable类似,但是功能更强大,具体表现在 a.可以在任务结束后提供一个返回值,Run ...

  3. Java通过继承thread类与实现Runnable接口实现多线程的区别

    Java中线程的创建有两种方式: 1.  通过继承Thread类,重写Thread的run()方法,将线程运行的逻辑放在其中 2.  通过实现Runnable接口,实例化Thread类 一.通过继承T ...

  4. Runnable和Callable接口辨析

    突然发现和启动一个线程有关的有三函数,run(), call(), start(),有点小乱,所以特别梳理一下 首先说一下start(),这个是最好说的,感觉start()和run()这俩名字是真的有 ...

  5. 关于Thread的Runnable和Callable接口

    其实非常简单:其实他们的区别就是Callable有返回值并且可以抛出异常. /** * Represents a command that can be executed. Often used to ...

  6. 实现Callable接口实现多线程

    package com.roocon.thread.t2; import java.util.concurrent.Callable; import java.util.concurrent.Exec ...

  7. callable接口的多线程实现方式

    package com.cxy.juc; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionExce ...

  8. java 多线程:Callable接口;FutureTask类实现对象【Thread、Runnable、Callable三种方式实现多线程的区别】

    Callable接口介绍: Java5开始,Java提供了Callable接口,像是Runnable接口的增强版,Callable接口提供了一个 call()方法可以作为线执行体. call()方法比 ...

  9. Java:多线程,分别用Thread、Runnable、Callable实现线程

    并发性(concurrency)和并行性(parallel)是两个概念,并行是指在同一时刻,有多条指令在多个处理器上同时执行:并发指在同一时刻只能有一条指令执行,但多个进程指令被快速轮换执行,使得宏观 ...

随机推荐

  1. KotlinMall实战之注册部分MVP架构配置

    包目录如下: ①BaseView部分:基本的回调 interface BaseView { fun showLoading() fun hideLoading() fun onError()} ②Ba ...

  2. 国产化之银河麒麟.netcore3.1访问https服务的两个问题

    背景 某个项目需要实现基础软件全部国产化,其中操作系统指定银河麒麟,数据库使用达梦V8,CPU平台的范围包括x64.龙芯.飞腾.鲲鹏等. 考虑到这些基础产品对.NETCore的支持,最终选择了3.1版 ...

  3. 人机验证reCAPTCHA v3使用完备说明

    v2简介 相信大家都碰到过下面的展示的 人机验证界面: reCaptcha 是 Google 公司的验证码服务,方便快捷,改变了传统验证码需要输入n位失真字符的特点. reCaptcha 在使用的时候 ...

  4. 视网膜血管分割代码(Pytorch实现)

    创建日期: 2021-12-24 17:00:00 update log(2021.12.24):B站视频删除了,回放看了一下,讲的不太行......2333,时间过得真快,转眼就是2022年了啊 2 ...

  5. 实体linux服务器-由自动ip改为固定ip后,无法上网问题--配置问题解法

    新入公司,研发产业为零,开始搞. linux之前是自动获取ip地址的,网上搜索的帖子,耍流氓的居多,不能上网的原因很多,我这个是配置不对,看是否与你的一样. 1.首先看下当前电脑网卡,根据地址可以判断 ...

  6. elasticSearch 7.6.1 入门及elasticSearch整合springboot

    一.ElasticSearch概述 官网:https://www.elastic.co/cn/downloads/elasticsearch Elaticsearch,简称为es,es是一个开源的高扩 ...

  7. linux下虚拟环境venv的创建与使用以及virtualenvwrapper

    1.linux安装学习python虚拟环境 linux提供的虚拟环境工具 有virtualenv pipenv 2.我们需求是在linux上可以运行 一个django2 运行一个django1 3.安 ...

  8. a commponent required a bean of type XXXXXX that could not be found-2022新项目

    一.问题由来 目前刚入职一家新公司不久,公司的新项目采用DDD驱动领域设计来进行开发,架构这一块使用的是阿里巴巴开源的最新框架COLA4.0的架构. 主要是这个框架里面的分层设计.主要分为四层:ada ...

  9. OAuth2.0笔记

    OAuth2.0笔记 角色 一般资源服务器和授权服务器是一个 资源拥有者 客户端应用 资源服务器 授权服务器 客户端类型 OAuth 2.0规范定义了两种客户端类型: 保密的:web应用 公有的:用户 ...

  10. Spring Boot整合模板引擎jsp

    jsp也算是一种模板引擎吧.整合jsp前,先说一下运行SpringBoot项目的几种方式 1. 运行SpringBoot项目的几种方式 1.1 使用内嵌Tomcat运行项目 在IDE中右键运行启动类, ...