Callable接口、Future接口、FutureTask类

以下内容转自:http://blog.csdn.net/ghsau/article/details/7451464   ;http://www.cnblogs.com/whgw/archive/2011/09/28/2194760.html

Callable接口

Callable接口类似于Runnable,但是Runnable不会返回结果并且无法抛出返回结果的异常,而Callable功能更强大一些,被线程执行后,可以返回值,则个返回值可以被Future拿到,Future可以拿到异步执行任务的返回值。

 

Callable的接口定义如下;

public interface Callable<V> { 

      V   call()   throws Exception; 

Callablle接口和Runnable接口的区别:

  • Callable定义的方法是call,而Runnable定义的方法是run。
  • Callable的call方法可以有返回值,而Runnable的run方法不能有返回值;
  • Callable的call方法可以抛出异常,而Runnable的run方法不能抛出异常。

 

Future接口---------public interface Future<V> 

V是词Future的get方法所返回的结果类型,Future标识异步计算的结果,它提供了检查计算是否完成的方法,以等待计算的完成,并获取计算的结果。计算完成后只能使用Get方法来获取结果。如果有必要,计算完成前可以阻塞此方法,取消则由cancle方法来执行。

如果为了可取消性而使用Future但又不提供可用的结果,则可以声明Future<?>形式类型、并返回null作为底层任务的结果。

功能:

1. boolean cancle(boolean mayInterruptIfRunning)---------试图取消对此任务的执行;一旦计算完成就不能再取消计算。参数为 true 表示立即中断任务的执行,参数为 false 表示允许正在运行的任务运行完成。

2. V  get()------------如有必要,等待计算完成,然后获取其结果

3.V   get(long timeout, TimeUnit unit)-----------如有必要,最多等待为使计算完成所给定的时间之后,获取其结果。

4.boolean isCancelled()----------如果在任务正常完成前将其取消,则返回true。

5.isDone()-----------如果任务已完成,则返回true。

package Test;

import java.util.concurrent.*;

interface ArchiveSearcher { String search(String target); }
class App {
    ExecutorService executor = Executors.newSingleThreadExecutor();
    ArchiveSearcher searcher = new ArchiveSearcher() {
        @Override
        public String search(String target) {
            return "zhaodaole";
        }
    };
    void showSearch(final String target) throws InterruptedException {
        Future<String> future = executor.submit(new Callable<String>() {
            public String call() {
                return searcher.search(target);
            }});
        try {
            SystedisplayText(future.get()); 
        } catch (ExecutionException ex) {
            return;
        }
    }
    public static void main(String[] args){
        try {
            new App().showSearch("nihao");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    public void SystedisplayText(String str){
        System.out.println("result="+str);
    }
}

 

FutureTask类

FutureTask实现了Runnable, Future<V>, RunnableFuture<V>  接口,所以它既可以作为Runnable被线程执行,又可以作为Future得到Callable的返回值。

那么这个组合的使用有什么好处呢?假设有一个很耗时的返回值需要计算,并且这个返回值不是立刻需要的话,那么就可以使用FutureTask,用另一个线程去计算返回值,而当前线程在使用这个返回值之前可以做其他的操作,等到需要这个返回值时,再通过Future到的。

仅在计算完成时才能获取结果,如果计算尚未完成,则阻塞get方法,一旦计算完成,就不能再重新开始或者取消计算。

可以使用FutureTask包装Callable或者Runnable对象,因为FutureTask实现了Runnable,所以可以将FutureTask提交给Executor执行。

示例:

import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class CallableAndFuture {
    public static void main(String[] args) {
        Callable<Integer> callable = new Callable<Integer>() {
            public Integer call() throws Exception {
                return new Random().nextInt(100);
            }
        };
        FutureTask<Integer> future = new FutureTask<Integer>(callable);
        new Thread(future).start();
        try {
            Thread.sleep(5000);// 可能做一些事情
            System.out.println(future.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}

 现在我们不直接创建线程并开启线程,而是通过ExecutorService的submit方法执行Callable中的call():

public static void method(){
        ExecutorService executorService=Executors.newSingleThreadExecutor();
        Future<Integer> future=executorService.submit(new Callable<Integer>(){

            @Override
            public Integer call() throws Exception {
                return new Random().nextInt(100);
            }
        });
        try{
            Thread.sleep(500);//doSomething
            System.out.println(""+future.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }

 或是:

public static void method(){
        FutureTask futureTask=new FutureTask(new Callable<Integer>(){

            @Override
            public Integer call() throws Exception {
                return new Random().nextInt(100);
            }
        });
        Executor executor=Executors.newSingleThreadExecutor();
        executor.execute(futureTask);
        try{
            Thread.sleep(500);//doSomething
            System.out.println(""+futureTask.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }

 

posted @ 2018-03-19 20:40  Garcia11  阅读(182)  评论(0)    收藏  举报