Java并发编程—说说Runnable与Callable
原文作者:每天一点
原文地址:说说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();
}
相同点:
- 两者都是接口;(废话)
- 两者都可用来编写多线程程序;
- 两者都需要调用Thread.start()启动线程;
不同点:
- 两者最大的不同点是:实现Callable接口的任务线程能返回执行结果;而实现Runnable接口的任务线程不能返回结果;
- 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相关推荐
- Java并发编程举例Runnable, Callable, Future, FutureTask, CompletionService
import java.util.concurrent.*;/*** Created by chenh on 2017/3/23.*/ public class ConcurrentDemo {// ...
- Java并发编程-Executor框架之Callable和Future接口
在上一篇文章中我们已经了解了Executor框架进行线程管理,这篇文章将学习Executor框架的另一个特性,我们知道执行Runnable任务是没有返回值得,但Executor可以运行并发任务并获得返 ...
- 15、Java并发编程:Callable、Future和FutureTask
Java并发编程:Callable.Future和FutureTask 在前面的文章中我们讲述了创建线程的2种方式,一种是直接继承Thread,另外一种就是实现Runnable接口. 这2种方式都有一 ...
- Java并发编程71道面试题及答案
Java并发编程71道面试题及答案 1.在java中守护线程和本地线程区别? java中的线程分为两种:守护线程(Daemon)和用户线程(User). 任何线程都可以设置为守护线程和用户线程,通过方 ...
- Java并发编程有多难?这几个核心技术你掌握了吗?
本文主要内容索引 1.Java线程 2.线程模型 3.Java线程池 4.Future(各种Future) 5.Fork/Join框架 6.volatile 7.CAS(原子操作) 8.AQS(并发同 ...
- 基于JVM原理、JMM模型和CPU缓存模型深入理解Java并发编程
许多以Java多线程开发为主题的技术书籍,都会把对Java虚拟机和Java内存模型的讲解,作为讲授Java并发编程开发的主要内容,有的还深入到计算机系统的内存.CPU.缓存等予以说明.实际上,在实际的 ...
- Java 并发编程——Executor框架和线程池原理
Java 并发编程系列文章 Java 并发基础--线程安全性 Java 并发编程--Callable+Future+FutureTask java 并发编程--Thread 源码重新学习 java并发 ...
- Java并发编程75道面试题及答案
1.在java中守护线程和本地线程区别?java中的线程分为两种:守护线程(Daemon)和用户线程(User).任何线程都可以设置为守护线程和用户线程,通过方法Thread.setDaemon(bo ...
- Java并发编程中的若干核心技术,向高手进阶
来源:http://www.jianshu.com/p/5f499f8212e7 引言 本文试图从一个更高的视角来总结Java语言中的并发编程内容,希望阅读完本文之后,可以收获一些内容,至少应该知道在 ...
最新文章
- 人工智能学习知识框架(知识点、实际应用)-思维导图汇总-xmind原图
- table切换数据 vue_Vue 知识整合贴 ( 超干货,适合收藏)
- 教之初计算机考试函数应用题,教之初计算机考试系统
- [vue] 从0到1自己构架一个vue项目,说说有哪些步骤、哪些重要插件、目录结构你会怎么组织
- 互联网日报 | 3月13日 星期六 | 蚂蚁集团公布碳中和目标;小鹏汽车累计交付突破50000台;阿迪达斯发未来五年新战略...
- Logstash+Kibana+多ElasticSearch集群部署
- Tomcat免安装版执行tomcat9.exe闪退
- Kinect 深度测量原理
- Multisim14.1中/英文版软件下载和安装教程|兼容WIN10
- 象棋( Xiangqi, ACM/ICPC Fuzhou 2011, UVa1589)
- 遇见你,是我幸福的开始
- 嵌入式Linux内核配置、裁剪与编译浅析(ARM版)
- webpack Uncaught ReferenceError: Swiper is not defined
- linux界面回收站图标没了,Ubuntu美化教程:在AWN中添加“显示桌面”和“回收站”图标...
- 从语义分析到操作系统,图灵机器人明年就能走进你家?
- 人际交往中的沟通五大原则
- XStream使用方法
- U-Net网络结构详解
- ccs用C语言进行printf时,DSP:CCS V6 TMS320F2812 使用printf函数
- mysql 无限层级传销_直销几个层级是传销