原文作者:每天一点

原文地址:说说Runnable与Callable

首先,我们先看看使用Callable创建线程与使用Runable的区别:

import java.util.concurrent.Callable;//实现Runable
class MyThread implements Runnable {@Overridepublic void run() {}
}//实现Callable
class MyThread1 implements Callable<Integer> {@Overridepublic Integer call() throws Exception {return null;}
}

首先,实现Callable而重写的方法具有返回值,并且拥有泛型,这提高了线程的细粒度。

实现Runable接口创建线程方式:

//实现Runable创建线程的方式
MyThread myThread = new MyThread();
Thread thread = new Thread(myThread);

实现Callable接口创建线程方式

查阅API我们可以发现,在Thread的构造方法中并没有使用Callable作为参数的构造器。解决办法:我们先查看Runable接口,

可以发现有一个FutureTask的实现类,点进这个实现类,我们可以发现在这个类的构造方法中就可以传Callable对象

所以我们可以借助FutureTask这个类,具体创建代码如下:

//实现Callable创建线程的方式
FutureTask futureTask = new FutureTask(new MyThread1());
Thread thread1 = new Thread(futureTask);

这里有个细节:如果我们在使线程睡眠5秒钟,然后使用futureTask.get()方法,会发现结果会等5秒才出现,说明get()方法是有阻塞效果

//实现Callable
class MyThread1 implements Callable<Integer> {@Overridepublic Integer call() throws Exception {System.out.println("进入方法中");Thread.sleep(5000);return 1000;}
}public class Test {public static void main(String[] args) {//实现Callable创建线程的方式FutureTask futureTask = new FutureTask(new MyThread1());new Thread(futureTask, "AAA").start();try {System.out.println(futureTask.get());System.out.println("main");} catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();}}
}

并且只执行了一次,因为一个futureTask,不管几个线程调用,调用的都是同一个futureTask对象

Callable接口:

public interface Callable<V> {V call() throws Exception;
}

Runnable接口:

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

相同点:

  1. 两者都是接口;(废话)
  2. 两者都可用来编写多线程程序;
  3. 两者都需要调用Thread.start()启动线程;

不同点:

  1. 两者最大的不同点是:实现Callable接口的任务线程能返回执行结果;而实现Runnable接口的任务线程不能返回结果;
  2. Callable接口的call()方法允许抛出异常;而Runnable接口的run()方法的异常只能在内部消化,不能继续上抛;

注意点:

  • Callable接口支持返回执行结果,此时需要调用FutureTask.get()方法实现,此方法会阻塞主线程直到获取‘将来’结果;当不调用此方法时,主线程不会阻塞!

写此篇的原因是一次面试中问到Callable与Runnable的区别,当时用的多的是Runnable,而Callable使用很少!比较了两者后(网上查了不少),发现Callable在很多特殊的场景下还是很有用的!最后留点抄的代码,加深对Callable的认识!

package com.inte.fork;
import java.util.*;
import java.util.concurrent.*;
import static java.util.Arrays.asList;public class Sums {static class Sum implements Callable<Long> {private final long from;private final long to;Sum(long from, long to) {this.from = from;this.to = to;}@Overridepublic Long call() {long acc = 0;for (long i = from; i <= to; i++) {acc = acc + i;}System.out.println(Thread.currentThread().getName() + " : " + acc);return acc;}}public static void main(String[] args) throws Exception {ExecutorService executor = Executors.newFixedThreadPool(3);List<Future<Long>> results = executor.invokeAll(asList(new Sum(0, 10), new Sum(0, 1_000), new Sum(0, 1_000_000)));executor.shutdown();for (Future<Long> result : results) {System.out.println(result.get());}}
}

Java并发编程—说说Runnable与Callable相关推荐

  1. Java并发编程举例Runnable, Callable, Future, FutureTask, CompletionService

    import java.util.concurrent.*;/*** Created by chenh on 2017/3/23.*/ public class ConcurrentDemo {// ...

  2. Java并发编程-Executor框架之Callable和Future接口

    在上一篇文章中我们已经了解了Executor框架进行线程管理,这篇文章将学习Executor框架的另一个特性,我们知道执行Runnable任务是没有返回值得,但Executor可以运行并发任务并获得返 ...

  3. 15、Java并发编程:Callable、Future和FutureTask

    Java并发编程:Callable.Future和FutureTask 在前面的文章中我们讲述了创建线程的2种方式,一种是直接继承Thread,另外一种就是实现Runnable接口. 这2种方式都有一 ...

  4. Java并发编程71道面试题及答案

    Java并发编程71道面试题及答案 1.在java中守护线程和本地线程区别? java中的线程分为两种:守护线程(Daemon)和用户线程(User). 任何线程都可以设置为守护线程和用户线程,通过方 ...

  5. Java并发编程有多难?这几个核心技术你掌握了吗?

    本文主要内容索引 1.Java线程 2.线程模型 3.Java线程池 4.Future(各种Future) 5.Fork/Join框架 6.volatile 7.CAS(原子操作) 8.AQS(并发同 ...

  6. 基于JVM原理、JMM模型和CPU缓存模型深入理解Java并发编程

    许多以Java多线程开发为主题的技术书籍,都会把对Java虚拟机和Java内存模型的讲解,作为讲授Java并发编程开发的主要内容,有的还深入到计算机系统的内存.CPU.缓存等予以说明.实际上,在实际的 ...

  7. Java 并发编程——Executor框架和线程池原理

    Java 并发编程系列文章 Java 并发基础--线程安全性 Java 并发编程--Callable+Future+FutureTask java 并发编程--Thread 源码重新学习 java并发 ...

  8. Java并发编程75道面试题及答案

    1.在java中守护线程和本地线程区别?java中的线程分为两种:守护线程(Daemon)和用户线程(User).任何线程都可以设置为守护线程和用户线程,通过方法Thread.setDaemon(bo ...

  9. Java并发编程中的若干核心技术,向高手进阶

    来源:http://www.jianshu.com/p/5f499f8212e7 引言 本文试图从一个更高的视角来总结Java语言中的并发编程内容,希望阅读完本文之后,可以收获一些内容,至少应该知道在 ...

最新文章

  1. 人工智能学习知识框架(知识点、实际应用)-思维导图汇总-xmind原图
  2. table切换数据 vue_Vue 知识整合贴 ( 超干货,适合收藏)
  3. 教之初计算机考试函数应用题,教之初计算机考试系统
  4. [vue] 从0到1自己构架一个vue项目,说说有哪些步骤、哪些重要插件、目录结构你会怎么组织
  5. 互联网日报 | 3月13日 星期六 | 蚂蚁集团公布碳中和目标;小鹏汽车累计交付突破50000台;阿迪达斯发未来五年新战略...
  6. Logstash+Kibana+多ElasticSearch集群部署
  7. Tomcat免安装版执行tomcat9.exe闪退
  8. Kinect 深度测量原理
  9. Multisim14.1中/英文版软件下载和安装教程|兼容WIN10
  10. 象棋( Xiangqi, ACM/ICPC Fuzhou 2011, UVa1589)
  11. 遇见你,是我幸福的开始
  12. 嵌入式Linux内核配置、裁剪与编译浅析(ARM版)
  13. webpack Uncaught ReferenceError: Swiper is not defined
  14. linux界面回收站图标没了,Ubuntu美化教程:在AWN中添加“显示桌面”和“回收站”图标...
  15. 从语义分析到操作系统,图灵机器人明年就能走进你家?
  16. 人际交往中的沟通五大原则
  17. XStream使用方法
  18. U-Net网络结构详解
  19. ccs用C语言进行printf时,DSP:CCS V6 TMS320F2812 使用printf函数
  20. mysql 无限层级传销_直销几个层级是传销

热门文章

  1. Android开发之基本概念
  2. cursor_sharing='SIMILAR'将被废弃
  3. 一段始终保持在最底部的div css代码
  4. vs2005之主题与皮肤的学习
  5. Oracle学习(十三)优化专题 【持续更新】
  6. [EffectiveC++]item22:Declare data members private
  7. 2.数据中心网络演进
  8. python中with语句的使用
  9. mdp文件-Chapter4-MD.mdp
  10. BZOJ 2342: 【SHOI2011】 双倍回文