java并发编程:Callable、Future和FutureTask
2015-01-29 14:32
471 查看
1.问题引入
创建线程有2中方式:直接继承Thread和实现Runnable接口。但是这2种方式都有一个缺陷,那就是执行完任务之后无法获取执行结果。
如果需要获取执行结果,就必须通过共享变量或者使用线程通信的方式来达到效果,但这样使用起来非常麻烦。
所以,自从jdk1.5之后,就提供了Callable和Future,通过他们可以获得任务执行完毕之后得到任务的执行结果。
2.Callable和Runnable
先说一下Runnable接口,在其中只声明了一个run()方法
Callable位于java.util.concurrent包下,也是一个接口,在里面也是只声明了一个方法:
那么如何使用Callable呢?一般情况下需要配合ExecutorService,在ExecutorService接口中声明了若干个submit方法的重载版本
3.Future
Future就是对具体的Runnable或者Callable任务的结果进行取消、查询是否完成、获取结果。必要时可以通过get方法获取执行结果,该方法会阻塞直到任务返回结果
Future位于java.util.concurrent包下:
(1)中断任务 (2)判断任务是否完成 (3)获取任务执行结果
因为Future只是一个接口,所以是无法直接用来创建对象使用的,因此有了下面的FutureTask
4.FutureTask
先看一下FutureTask的声明
FutureTask的构造器
5.使用实例
(1)使用Callable+Future获取执行结果
(2)使用Callable+FutureTask获取执行结果
创建线程有2中方式:直接继承Thread和实现Runnable接口。但是这2种方式都有一个缺陷,那就是执行完任务之后无法获取执行结果。
如果需要获取执行结果,就必须通过共享变量或者使用线程通信的方式来达到效果,但这样使用起来非常麻烦。
所以,自从jdk1.5之后,就提供了Callable和Future,通过他们可以获得任务执行完毕之后得到任务的执行结果。
2.Callable和Runnable
先说一下Runnable接口,在其中只声明了一个run()方法
public interface Runnable { public abstract void run(); }由于run()方法返回值为void类型,所以在执行完任务之后,无法返回任何结果。
Callable位于java.util.concurrent包下,也是一个接口,在里面也是只声明了一个方法:
public interface Callable<V> { V call() throws Exception; }可以看到,这是一个泛型接口,call()返回的类型就是传递进来的泛型
那么如何使用Callable呢?一般情况下需要配合ExecutorService,在ExecutorService接口中声明了若干个submit方法的重载版本
<T> Future<T> submit(Callable<T> task); <T> Future<T> submit(Runnable task, T result); Future<?> submit(Runnable task);第一个submit方法里的参数类型就是Callable。一般我们使用第一和第三个方法
3.Future
Future就是对具体的Runnable或者Callable任务的结果进行取消、查询是否完成、获取结果。必要时可以通过get方法获取执行结果,该方法会阻塞直到任务返回结果
Future位于java.util.concurrent包下:
public interface Future<V> { boolean cancel(boolean mayInterruptIfRunning); //用来取消任务,参数表示是否能够取消正在执行却没有执行完成的任务 boolean isCancelled(); //用来表示任务是否被取消成功,如果在任务正常完成前被取消成功,则返回true boolean isDone(); //表示任务是否已经完成,如果任务完成则返回true V get() throws InterruptedException, ExecutionException; //用来获取执行结果,这个方法会产生阻塞,会一直等到任务执行完毕才返回 V get(long timeout, TimeUnit unit) //获取执行结果,如果在指定时间内还没有取到结果,就直接返回null throws InterruptedException, ExecutionException, TimeoutException; }简单地说,Future提供了3种功能:
(1)中断任务 (2)判断任务是否完成 (3)获取任务执行结果
因为Future只是一个接口,所以是无法直接用来创建对象使用的,因此有了下面的FutureTask
4.FutureTask
先看一下FutureTask的声明
public class FutureTask<V> implements RunnableFuture<V>FutureTask实现了RunnableFuture接口,我们看一下RunnableFuture接口的实现
public interface RunnableFuture<V> extends Runnable, Future<V> { void run(); }可以看出FutureTask实现了RunnableFuture接口,RunnableFuture接口继承了Runnable和Future接口,所以FutureTask既可以作为线程执行,又可以作为Future得到Callable的返回值
FutureTask的构造器
public FutureTask(Callable<V> callable) { if (callable == null) throw new NullPointerException(); this.callable = callable; this.state = NEW; // ensure visibility of callable } public FutureTask(Runnable runnable, V result) { this.callable = Executors.callable(runnable, result); this.state = NEW; // ensure visibility of callable }可以看出不论是使用Callable还是Runnable,最终都是转换为Callable
5.使用实例
(1)使用Callable+Future获取执行结果
class Task implements Callable<Integer> { @Override public Integer call() throws Exception { System.out.println("sub thread is running"); Thread.sleep(3000); int sum = 0; for(int i=1; i<100; i++) sum += i; return sum; } } public class TestFuture { public static void main(String[] args) { ExecutorService executorService = Executors.newCachedThreadPool(); Task task = new Task(); Future<Integer> result = executorService.submit(task); executorService.shutdown(); try { Thread.sleep(1000); } catch (InterruptedException e1) { e1.printStackTrace(); } try { System.out.println(result.get()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } }结果为:
sub thread is running 4950
(2)使用Callable+FutureTask获取执行结果
public static void main(String[] args) { ExecutorService executorService = Executors.newCachedThreadPool(); Task task = new Task(); FutureTask<Integer> futureTask =new FutureTask<>(task); executorService.submit(futureTask); executorService.shutdown(); try { Thread.sleep(1000); } catch (InterruptedException e1) { e1.printStackTrace(); } try { System.out.println(futureTask.get()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } }结果与上面完全相同
相关文章推荐
- Java并发编程:Callable、Future和FutureTask
- Java并发编程:Callable、Future和FutureTask
- Java并发编程:Callable、Future和FutureTask
- Java并发编程:Callable、Future和FutureTask
- Java并发编程:Callable、Future和FutureTask
- Java并发编程:Callable、Future和FutureTask
- Java并发编程:Callable、Future和FutureTask
- Java并发编程:Callable、Future和FutureTask
- Java并发编程:Callable、Future和FutureTask
- Java并发编程:Callable、Future和FutureTask
- Java并发编程:Callable、Future和FutureTask
- Java并发编程:Callable、Future和FutureTask
- 15、Java并发编程:Callable、Future和FutureTask
- Java并发编程:Callable、Future和FutureTask
- Java并发编程:Callable、Future和FutureTask
- Android AsyncTask完全解析FutureTask 深度解析 -Java并发编程:Callable、Future和FutureTask一个使用DownloadManager下载文件的小例
- 线程池二:Java并发编程:Callable、Future和FutureTask
- Java并发编程:Callable、Future和FutureTask
- Java并发编程:Callable、Future和FutureTask
- Java并发编程:Callable、Future和FutureTask