Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Callable and Future in Java(java中的Callable和Future)

Callable and Future in Java(java中的Callable和Future)

作者头像
冬天里的懒猫
发布于 2020-09-28 03:17:18
发布于 2020-09-28 03:17:18
49200
代码可运行
举报
运行总次数:0
代码可运行

需要Callable的理由

通常,我们有两种方式创建线程,一种方式是继承Thread类,另外一种方式是实现Runnable接口。然而,Runnable方式缺少的一个特性就是,当线程终止的时候,即run运行完成的时候,我们布恩那个让线程返回一个执行结果。为了之处这个特性,在java中就增加了Callable接口。

Callable vs Runnable

  • 为了实现Runnable接口,需要实现不返回任何返回值的run方法,而对于callable,我们需要实现在完成的时候,返回接口的call方法,注意,线程不能用Callable创建,只能用Runnbale的方式创建。
  • 另外一个区别就是,call方法可以抛出异常。而run方法则不能。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public Object call() throws Exception;

如下是Callable的代码示例,它将在大约0-4秒之后返回一个随机数:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class CallableExample implements Callable {

	@Override
	public Object call() throws Exception {
		Random generator = new Random();
		Integer randomNumber = generator.nextInt(5);
		TimeUnit.SECONDS.sleep(randomNumber);

		return randomNumber;
	}
	
}

Future

当call方法执行完成的时候,计算结果必须存储在main线程的已知对象中,以便mian线程可以值得这个call线程的返回结果,但是程序在此后将如何存储和获得这个结果呢? 为此,我们需要使用Future丢箱,可以将Future看作一个持有结果的对象,它可能现在不持有结果,但是将来,一旦Callable执行完成,就会这样做,因此,Futrue基本上是利用主线程跟踪其他线程结果的一种方式,要实现这个接口,需要重写5个方法,以下示例是其具体实现,在此,我们只列出了重要的方法。 需要注意的是,Callable和Future做了两件不同的事情,Callable和Runnable类似,因为它封装了一个任务,该任务在另外一个线程上运行,而Future用于存储从另外一个线程获得的结果,事实上,未来也可以使用Runnable,这一点在Executors参与之后就会变得很清晰。

  • public boolean cancel(boolean mayInterrupt): 用于停止任务,如果任务尚未启动,他将停止该任务,如果任务已经启动,则在manInteerrupt为ture的时候中断该任务。
  • public Object get() throws InterruptedException, ExecutionException:用于获得任务的结果,如果任务完成,则立即返回结果,否则等待任务完成,然后返回结果。
  • public boolean isDone():如果任务完成,则返回true,否则,返回false。

如果需要创建线程,那么细羽一个Runnable,如果需要取得结果,那么需要一个Future。 在java中,具体的类似是FutureTask,它实现了Runnable和Future,方便地结合了这两种功能。 FutureTask可以通过为其提供的构造函数来创建Callable,然后将FutureTask对象提供给Thread的构造函数来创建Thread对象。因此,间接的实现了Callable创建线程。在此要重点强调的是,没有办法直接用Callable创建线程。 如下是Callable和FutureTask的完整示例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class CallableExample implements Callable {

	@Override
	public Object call() throws Exception {
		Random generator = new Random();
		Integer randomNumber = generator.nextInt(5);
		TimeUnit.SECONDS.sleep(randomNumber);

		return randomNumber;
	}

}

public class CallableFutureTest {
	public static void main(String[] args) throws Exception
	{

		// FutureTask is a concrete class that
		// implements both Runnable and Future
		FutureTask[] randomNumberTasks = new FutureTask[5];

		for (int i = 0; i < 5; i++)
		{
			Callable callable = new CallableExample();

			// Create the FutureTask with Callable
			randomNumberTasks[i] = new FutureTask(callable);

			// As it implements Runnable, create Thread
			// with FutureTask
			Thread t = new Thread(randomNumberTasks[i]);
			t.start();
		}

		for (int i = 0; i < 5; i++)
		{
			// As it implements Future, we can call get()
			System.out.println(randomNumberTasks[i].get());

			// This method blocks till the result is obtained
			// The get method can throw checked exceptions
			// like when it is interrupted. This is the reason
			// for adding the throws clause to main
		}
	}
}

执行结果:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
2
2
3
4
0

线程启动后与它所有的交互都使用FutureTask对象来实现Future接口,因此,不需要存储线程对象,使用TutureTask对象,可以实现对task的取消,以及检查它释放完成或者尝试获得其执行结果。 如下是通过Runnable实现类型功能的代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class RunnableExample implements Runnable {

	private Object result = null;

	@Override
	public void run() {
		Random generator = new Random();
		Integer randomNumber = generator.nextInt(5);

		// As run cannot throw any Exception
		try {
			Thread.sleep(randomNumber * 1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

		// Store the return value in result when done
		result = randomNumber;

		// Wake up threads blocked on the get() method
		synchronized (this) {
			notifyAll();
		}
	}

	public synchronized Object get()
			throws InterruptedException {
		while (result == null) {
			wait();
		}

		return result;
	}
}

public class RunnableTest {

	public static void main(String[] args) throws Exception {
		RunnableExample[] randomNumberTasks = new RunnableExample[5];

		for (int i = 0; i < 5; i++) {
			randomNumberTasks[i] = new RunnableExample();
			Thread t = new Thread(randomNumberTasks[i]);
			t.start();
		}

		for (int i = 0; i < 5; i++) {
			System.out.println(randomNumberTasks[i].get());
		}
	}
}

输出:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
4
4
0
2
3

参考

https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Callable.html https://docs.oracle.com/javase/7/docs/api/java/lang/Runnable.html https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/FutureTask.html

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020/09/25 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Callable/Future 使用及原理分析,Future .get()为啥能等待呢?
Callable/Future 和 Thread 之类的线程构建最大的区别在于,能够很方便的获取线程执行完以后的结果。首先来看一个简单的例子
源码之路
2020/09/04
5K0
Callable/Future 使用及原理分析,Future .get()为啥能等待呢?
Java线程(七):Callable和Future
本文介绍了Java线程的Callable和Future,包括如何使用Callable创建有返回值的线程,以及如何使用Future获取返回值。同时介绍了ExecutorService、Future和CompletionService等工具类,用于简化线程并发编程。
高爽
2017/12/28
5710
Runnable和Callable源码及应用解析
里面使用Runnable的地方只有传递对象的时候,其他都是使用的Thread而Thread又实现了我们的Runnable,所以Runbale可以理解为执行代码的对象,执行的过程和线程的操作交由Thread控制,Thread源码可以看 ----》Thread源码解析。
余生大大
2022/11/02
1990
Runnable和Callable源码及应用解析
6.实现 Callable 接口
6.实现 Callable 接口 前言 本篇章来介绍一下创建线程的第三种方式,其中创建线程一共有四种方式: 继承 Thread 类 实现 Runnable 接口 实现 Callable 接口 使用线程池的方式 那么下面我们来介绍一下 实现 Callable 接口的方式。 Callable 接口 - Java 5.0 在 java.util.concurrent 提供了一个新的创建执行线程的方式:Callable 接口 - Callable 接口类似于 Runnable,两者都是为那些其实例可能被另一个线程
Devops海洋的渔夫
2022/03/23
5980
6.实现 Callable 接口
Thread, Runable, Callable 还傻傻分不清?
在java中你怎么创建线程?相信你很快能够想到继承Thread类和实现Runnable接口这两种方式。
Java技术栈
2020/12/21
7600
Thread, Runable, Callable 还傻傻分不清?
Runnable 和Callable的实现与区别,应用场景
1:通过实现Runnable接口 2:通过继承Thread接口 3:通过Callable和Future创建线程
全栈程序员站长
2022/07/25
1.5K0
Java并发之Executor + Callable + Future引入 Callable + FutureCallable + Future实例
Executor框架的优势之一就是,可以运行并发任务并且返回结果。 我们知道Runnable对象是没有返回值的,所以自然利用Runnable对象就无法返回结果,于是就定义了一个新的接口,可以理解为是“带有返回值的Runnable对象”。 这个接口就是 Callable接口:这个接口声明了一个call方法,类似于Runnable接口的run方法,是任务具体的逻辑,不同就在于可以有返回值,而且这个接口是一个泛型接口,这就意味着必须声明call方法的返回类型。
desperate633
2018/08/22
3110
Java并发之Executor + Callable + Future引入 Callable + FutureCallable + Future实例
创建线程都有哪些方式?— Callable篇
相信大家回答这个问题没什么难度吧?通常问完创建方式,那么接下来就是问「1、2」跟「3」创建方式的不同了,只要说出「3」有返回值基本这个问题就过了,不管是出于好奇还是疑惑,我们今天来会会这个Callable。
niceyoo
2020/07/26
8010
Callable与Future介绍
在Java中,创建线程一般有两种方式,一种是继承Thread类,一种是实现Runnable接口。然而,这两种方式的缺点是在线程任务执行结束后,无法获取执行结果。我们一般只能采用共享变量或共享存储区以及线程通信的方式实现获得任务结果的目的。不过,Java中,也提供了使用Callable和Future来实现获取任务结果的操作。Callable用来执行任务,产生结果,而Future用来获得结果。
HLee
2021/10/13
1K0
Callable与Future介绍
Future和Callable学习
我们知道使用多线程时,最初的Thread到线程池,此时对于线程的使用,提供了其使用的复用率。而实现多线程的三种方式:继承Thread;实现Runnable接口,重写run方法;实现Callable接口,同时重写call方法,同时通过Future获取执行的返回值。也就是说callable执行任务,而Future拿到执行的结果。Future具有阻塞性在于其get()方法具有阻塞性,而isDone()是不具有阻塞性的。
路行的亚洲
2020/07/16
5030
刚研究完Callable和Future,各位随便问!!
在Java的多线程编程中,除了Thread类和Runnable接口外,不得不说的就是Callable接口Future接口了。使用继承Thread类或者实现Runnable接口的线程,无法返回最终的执行结果数据,只能等待线程执行完成。此时,如果想要获取线程执行后的返回结果,那么,Callable和Future就派上用场了。
冰河
2021/04/30
6770
并发编程系列之Callable和Runnable的不同?
并发编程系列之Callable和Runnable的不同?在学习并发多线程的过程中,很多读者都知道怎么实现Runnable,下面是一道经典的例子
SmileNicky
2021/09/08
4131
并发编程系列之Callable和Runnable的不同?
Java并发编程之Future和FutureTask
搞过Java或者客户端Android开发的都知道,创建线程的2种方式,一种是直接继承Thread,另外一种就是实现Runnable接口。不过,这2种方式都有一个缺陷,就是在执行完任务之后无法获取执行结果。
xiangzhihong
2022/11/30
3680
Java中的Runnable、Callable、Future、FutureTask的区别
Java中存在Runnable、Callable、Future、FutureTask这几个与线程相关的类或者接口,在Java中也是比较重要的几个概念,我们通过下面的简单示例来了解一下它们的作用于区别。
开发者技术前线
2020/11/23
4620
Future && FutureTask
线程的创建方式中有两种,一种是实现Runnable接口,另一种是继承Thread,但是这两种方式都有个缺点,那就是在任务执行完成之后无法获取返回结果,于是就有了Callable接口,Future接口与FutureTask类的配和取得返回的结果。
大学里的混子
2019/03/13
5520
java 多线程
就绪,当线程调用了strat()方法的时候,线程就绪,会为其创建方法调用栈和程序计数器。
mySoul
2018/11/19
8100
简单理解Callable接口
Callable,新启线程的一种方式,返回结果并且可能抛出异常的任务,在前面的新启线程的文章中用过,但是没有具体讲解
彼岸舞
2020/11/06
8630
Future解析与使用
Java 1.5开始,提供了Callable和Future,通过它们可以在任务执行完毕之后得到任务执行结果。
林老师带你学编程
2019/05/25
5890
多线程(四) | 聊聊Callable和Future
通过前面几篇文章,我相信大家应该对于如何使用多线程执行任务应该都有了一定的了解。今天我们来讲一讲Callable和Future。
一缕82年的清风
2022/11/02
5570
Future FutrueTask Callable类源码说明以及原理使用
  JDK内置的Future主要使用到了Callable接口和FutureTask类。
小勇DW3
2018/08/30
5620
相关推荐
Callable/Future 使用及原理分析,Future .get()为啥能等待呢?
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验