Callable和Future

原文链接  译文链接  译者:Greenster  校对:沈义扬
Java从发布的第一个版本开始就可以很方便地编写多线程的应用程序,并在设计中引入异步处理。Thread类、Runnable接口和Java内存管理模型使得多线程编程简单直接。但正如之前提到过的,Thread类和Runnable接口都不允许声明检查型异常,也不能定义返回值。没有返回值这点稍微有点麻烦。

 不能声明抛出检查型异常则更麻烦一些。public void run()方法契约意味着你必须捕获并处理检查型异常。即使你小心地保存了异常信息(译者注:在捕获异常时)以便稍后检查,但也不能保证这个类(译者注:Runnable对象)的所有使用者都读取异常信息。你也可以修改Runnable实现的getter,让它们都能抛出任务执行中的异常。但这种方法除了繁琐也不是十分安全可靠,你不能强迫使用者调用这些方法,程序员很可能会调用join()方法等待线程结束然后就不管了。

但是现在不用担心了,以上的问题终于在1.5中解决了。Callable接口和Future接口的引入以及他们对线程池的支持优雅地解决了这两个问题。

Callable

Callable接口定义了方法public T call() throws Exception。我们可以在Callable实现中声明强类型的返回值,甚至是抛出异常。尽管在Executors类中已经有一些方法可以将Runnable对象转换为Callable对象,你最好还是仔细复审现有的Runnable实现或Thread的子类。为什么还要这样做?主要是为了检查和清除因为Runnable无法抛出检查型异常而采用的变通方案。同时,你可能希望利用call()方法直接返回结果的能力,以省去读取值时的类型转换。

Future

下面就将线程池和Callable接口相结合,看能发生怎样的效应。Future是Java 1.5中引入的接口,当你提交一个Callable对象给线程池时,将得到一个Future对象,并且它和你传入的Callable有相同的结果类型声明。这个对象取代了Java 1.5之前直接操作具体Thread实例的做法。过去你不得不用Thread.join()或者Thread.join(long millis)等待任务完成,而现在你可以像下面的例子那样做。

public class ServerAcceptingRequestsVerifier implements Callable {
	/**
	 * @return Boolean.TRUE is server is accepting requests
	 * Boolean.FALSE otherwise
	 */
	public Boolean call() throws Exception {
		Boolean isAcceptingRequests = null;
		... ask server about taking requests here
		return isAcceptingRequests;
	}
}
public Boolean isServerTakingRequests(String server)
			throws UnresponsiveException, InterruptedException {
	ServerAcceptingRequestsVerifier acceptingRequestsVerifier =
		new ServerAcceptingRequestsVerifier();
	Future future =
		THREAD_POOL.submit(acceptingRequestsVerifier);
	try {
		Boolean isAcceptingRequests = future.get();
		//waits for the thread to complete, even if it hasn't started
		return isAcceptingRequests;
	} catch (ExecutionException e) {
		throw new UnresponsiveException(e.getCause());
	}

}

如果要限制等待任务结束的时间,也可以添加一个捕获TimeoutException的catch子句

try {
	Boolean isAcceptingRequests = future.get(5, TimeUnit.SECONDS);
	//this waits for 5 seconds, throwing TimeoutException if not done
	return isAcceptingRequests;
} catch (TimeoutException e) {
	LOGGER.warn("Timed out waiting for server check thread." +
		"We'll try to interrupt it.");
	future.cancel(true);
	return Boolean.FALSE;
} catch (ExecutionException e) {
	throw new UnresponsiveException(e.getCause());
}

文章转自 并发编程网-ifeve.com

时间: 2024-12-23 23:36:38

Callable和Future的相关文章

java.util.concurrent包(4)——Callable和Future

Callable和Future,一个产生结果,一个拿到结果. Callable接口类似于Runnable,从名字就可以看出来了,但是Runnable不会返回结果,并且无法抛出返回结果的异常,而Callable功能更强大一些,被线程执行后,可以返回值,这个返回值可以被Future拿到,也就是说,Future可以拿到异步执行任务的返回值,下面来看一个简单的例子: public class CallableAndFuture {public static void main(String[] args

Java并发编程:Callable、Future和FutureTask

在前面的文章中我们讲述了创建线程的2种方式,一种是直接继承Thread,另外一种就是实现Runnable接口. 这2种方式都有一个缺陷就是:在执行完任务之后无法获取执行结果. 如果需要获取执行结果,就必须通过共享变量或者使用线程通信的方式来达到效果,这样使用起来就比较麻烦. 而自从Java 1.5开始,就提供了Callable和Future,通过它们可以在任务执行完毕之后得到任务执行结果. 今天我们就来讨论一下Callable.Future和FutureTask三个类的使用方法.以下是本文的目录

java自定义任务类定时执行任务示例 callable和future接口使用方法_java

Callable 和 Future接口Callable是类似于Runnable的接口,实现Callable接口的类和实现Runnable的类都是可被其它线程执行的任务. Callable和Runnable有几点不同: (1)Callable规定的方法是call(),而Runnable规定的方法是run().(2)Callable的任务执行后可返回值,而Runnable的任务是不能返回值的. (3)call()方法可抛出异常,而run()方法是不能抛出异常的.(4)运行Callable任务可拿到一

JDK5.0新特性系列---11.1线程 Callable和Future

  import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future;   /**     从本节开始,主要介绍J2SE5.0与线程相关的新特性,新的线程类主要集中在java.util.concurrent 包中,本节实例将介绍如何使用java.uti

java-并发-Callable、Future和FutureTask

创建线程的2种方式,一种是直接继承Thread,另外一种就是实现Runnable接口 区别:接口可以实现多继承 缺陷就是:在执行完任务之后无法获取执行结果 Callable与Runnable java.lang.Runnable public interface Runnable { public abstract void run(); } 由于run()方法返回值为void类型,所以在执行完任务之后无法返回任何结果. java.util.concurren public interface

关于多线程中的Callable 和 Future接口

问题描述 Callable中call方法的执行是原子操作吗?"Future的get()方法的调用被阻塞,直到计算完成"是指call方法执行过程中不会被cpu中断,只有call方法执行完毕才会将cpu资源让给其他线程吗?这是多线程的一种同步机制吗? 问题补充:飞雪无情 写道 解决方案 Future 表示异步计算的结果.它提供了检查计算是否完成的方法,以等待计算的完成,并获取计算的结果.这就是他从在的目的解决方案二:Future和Callable是一对,他俩基本上是搭配使用的.Future

CompletionService、Future

一.CompletionService接口提供了可以操作异步任务的功能,其唯一实现的API为ExecutorCompletionService.此API只是可以获取异步任务执行的结果,它不是ExecutorService. 其有5个核心方法: Future<V> poll():同步操作,获取并移除第一已经完成的任务,否则返回null. Future<V> poll(timeout):同步操作,获取并移除第一个已经完成的任务,阻塞时间为timeout,否则返回null:支持Inter

Java核心技术 卷Ⅰ 基础知识(原书第10版)

Java核心技术系列 Java核心技术 卷Ⅰ 基础知识 (原书第10版) Core Java Volume I-Fundamentals (10th Edition) [美] 凯S.霍斯特曼(Cay S. Horstmann) 著 周立新 陈 波 叶乃文 邝劲筠 杜永萍 译 图书在版编目(CIP)数据 Java核心技术 卷Ⅰ 基础知识(原书第10版) / (美)凯S. 霍斯特曼(Cay S. Horstmann)著:周立新等译. -北京:机械工业出版社,2016.8 (Java核心技术系列) 书

并发编程6-执行器

如果想开发服务器应用,应该有大的吞吐量和快速的响应.  这样就要求服务器段有清晰的任务边界和任务执行策略. 现在看一个服务器应用: public static void main(String[] args) throws IOException { ServerSocket ss = new ServerSocket(8080); while (true){ Socket s = ss.accept(); handleRequest(s); } } 顺序执行的,造成资源利用率低,  吞吐量或响