Java中的Callable和Future
来源:互联网 发布:淘宝网服装货源 编辑:程序博客网 时间:2024/06/07 14:28
原文地址:http://www.geeksforgeeks.org/callable-future-java/
Callable的用处
在Java中创建线程有两种方法——一种是继承Thread类,另一种是实现Runnable接口。但是Runnable没有的一个特点就是它不能在线程结束的时候返回结果,例如当run()结束了。Java中的Callable接口正好支持这个特征。
Callable vs Runnable
- 对于Runnable的实现,run()方法也得必须的实现,但是它不能返回任何东西,但是在Callable中,实现call()的话就可以在结束时返回结果。注意不能用Callable创建线程,线程只能用Runnable来创建。
- 另外的一个不同之处就是call()方法可以抛异常,但是run()不行。
实现Callable必须重载方法签名。
public Object call() throws Exception;
这里是一个Callable例子的代码,它在每0-4秒的延迟间隔会返回一个随机数。
// Java program to illustrate Callable// to return a random numberimport java.util.Random;import java.util.concurrent.Callable;import java.util.concurrent.FutureTask;class CallableExample implements Callable { public Object call() throws Exception { // Create random number generator Random generator = new Random(); Integer randomNumber = generator.nextInt(5); // To simulate a heavy computation, // we delay the thread for some random time Thread.sleep(randomNumber * 1000); return randomNumber; }}
Future
当一个call()方法执行完成的时候,结果就必须保存在main线程已知的对象中,这样main线程就可以知道这个线程返回的结果是什么。那么代码在后来是如何保存并获取这个结果的呢?对于这个问题,就可以用Future对象了。考虑一个Future对象得到这个结果——它可能不会立马拿到,但是将来(Future,一旦Callable返回)也会拿到。因此,一个Future实际就是main线程的一个路径,可以对其他线程的进度和结果进行跟踪。想要实现这个接口,有5个方法必须得重载,但是在下面的例子中用了一个具体的库实现,只有几个重要的方法列在了这里。
注意到Callable和Future做的是两种不同的事情——Callable类似于Runnable,它封装了任务并运行在其他的线程上,因此Future是用于从其他线程获取并存储结果。实际上,Future可以跟Runnable做的工作是一样的,这就使得在Executors出现的时候情况就变得更加清晰了。
- public boolean cancel(boolean mayInterrupt):用于停止任务。如果一个任务没有启动,那就停止它。如果已经启动了,并且mayInterrupt为true,那么就中断这个任务。
- public Object get() throws InterruptedException, ExecutionException: 用于得到任务的结果。如果任务完成了,它就立即返回结果,否则就等待任务的完成然后返回结果。
- public boolean isDone():如果一个任务完成了就返回true,否则返回false。
想创建线程,那就需要Runnable,想要得到结果,那就用Future。
Java库中有FutureType具体的类型,它实现了Runnable和Future,同时结合了两边的便捷。
FutureTask对象可以通过它的构造函数和Callable来创建,然后FutureTask将提供给Thread的构造函数来创建一个Thread对象。因此,Callable间接地创建了线程。再一次强调,Callable是不可能直接创建线程的。
这里是用Callable和FutureTask的例子代码:
// Java program to illustrate Callable and FutureTask// for random number generationimport java.util.Random;import java.util.concurrent.Callable;import java.util.concurrent.FutureTask;class CallableExample implements Callable { public Object call() throws Exception { Random generator = new Random(); Integer randomNumber = generator.nextInt(5); Thread.sleep(randomNumber * 1000); 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 } }}
输出:
42330
启动之后与线程的所有交互都是用实现Future接口的FutureTask对象。因此就没必要保存Thread对象了。利用FutureTask对象,可以取消任务,检查任务是否已经完成并尝试得到结果。
下面是只用Runnable的代码。
// Java program to illustrate Runnable// for random number generationimport java.util.Random;import java.util.concurrent.Callable;import java.util.concurrent.FutureTask;class RunnableExample implements Runnable { // Shared object to store result private Object result = null; 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; }}// Code is almost same as the previous example with a// few changes made to use Runnable instead of Callablepublic 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()); }}
输出示例:
043142
参考文献
- 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
- Java中的Callable和Future
- Java中的Callable和Future
- Java中的Callable和Future
- Java线程中的Callable和Future
- java callable和Future
- java中的Callable和Future的使用和困惑
- Java线程:Callable和Future
- 【Java线程】Callable和Future
- Java线程:Callable和Future
- java多线程Callable和Future
- Java线程:Callable和Future
- Java Future和Callable介绍
- 【Java线程】Callable和Future
- Java线程:Callable和Future
- Java线程:Callable和Future
- Java Callable和Future学习
- Java多线程--Callable和Future
- Java线程:Callable和Future
- Maven学习笔记----使用Maven创建Java项目
- ArcGIS9.3 插件开发的dll如何在ArcMap等桌面端产品用起来
- android 需要常量表达式
- cocos2dx lua开发调试打log方式
- 关于qt中的tr()函数
- Java中的Callable和Future
- Android全局异常捕捉
- sql中count或sum为条件的查询示例(sql查询count)
- mybatis 为什么要设置jdbcType
- scala(13)-----集合(Collection)-------Map(映射)
- 5分钟内搞定 Tomcat 的 SSL 配置
- php为什么是边编译边运行
- mongo-java-driver连接mongo集群
- 初识React