Callable与Future

来源:互联网 发布:色环电阻软件 编辑:程序博客网 时间:2024/05/18 00:07

本文可作为传智播客《张孝祥-Java多线程与并发库高级应用》的学习笔记。

在前面写的代码中,所有的任务执行也就执行了,run方法的返回值为空。

这一节我们说的Callable就是一个可以带返回值的线程模型。而它的返回值由Future接着。
先看看Callable
java.util.concurrent Interface Callable<V>
接口里面只有一个call方法,参数为空,返回值为T。

首先我们看看javadoc里面 Thread()的构造函数的参数没有Callable类型的,换言之,不能通过Thread().start的方式类运行Callable。

那么如何使用Callable呢?
有一个类叫
public class FutureTask<V> extends Object implements RunnableFuture<V>
其中RunnableFuture实现了Runnable接口。
而Runnable的构造函数的参数却可以使Callable。
说了这么多,我们看看代码:

使用FutureTask

public static void main(String[] args) {        Callable<Integer> callable = new Callable<Integer>() {              public Integer call() throws Exception {                  int a=new Random().nextInt(100);                System.out.println(a+"   ss");                return a;              }          };                  FutureTask<Integer> ft=new FutureTask<Integer>(callable);//        for (int i = 0; i < 5; i++)//            new Thread(ft).start();        //    new Thread(ft).start();        ft.run();        try {            System.out.println("得到结果 "+ft.get());        } catch (InterruptedException e) {            // TODO Auto-generated catch block            e.printStackTrace();        } catch (ExecutionException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }    }
运行结果
69   ss
得到结果 69
没有什么问题。
不过大家估计对代码中让new Thread(ft).start()运行5次的部分比较奇怪。
打开注释后,输出的结果还是两行,call方法只运行了一次。为什么?不知道。

我们再看看Future类



带参数的get,就是给个时间限制,如果再n个单位时间内,还没有获得结果,就抛出异常。

使用线程池

public static void main(String[] args) {    ExecutorService threadPool =  Executors.newSingleThreadExecutor();    Future<String> future =        threadPool.submit(            new Callable<String>() {                public String call() throws Exception {                    Thread.sleep(2000);                        return "hello";                };            }    );    System.out.println("等待结果");    //这里应该有trycatch    System.out.println("拿到结果:" + future.get());}
结果不再赘述。

多个任务

public static void main(String[] args) {                ExecutorService threadPool2 =  Executors.newFixedThreadPool(10);        CompletionService<Integer> completionService = new ExecutorCompletionService<Integer>(threadPool2);        for(int i=1;i<=10;i++){            final int seq = i;            completionService.submit(new Callable<Integer>() {                @Override                public Integer call() throws Exception {                    Thread.sleep(new Random().nextInt(5000));                    return seq;                }            });        }        for(int i=0;i<10;i++){            System.out.println(completionService.take().get());            //上面本应该有trycatch        }        threadPool2.shutdown();    }
运行结果

3
9
1
6
8
4
7
10
5
2

这句话completionService.take().get()具体是干什么的?
举个例子,你种了10亩地的麦子,等到秋天的时候,你如何割麦子呢?
当然是看那10亩地,那一亩先成熟,就先收割那一亩对吧。

completionService.submit了10个任务,completionService本身也不知道那个任务先执行完。completionService.take()就是获得已经执行完的那个任务的Future。

关于completionservice大家还可以看看下面这个资料

使用CompletionService批处理任务




感谢glt


参考资料

http://blog.csdn.net/ghsau/article/details/7451464
0 0
原创粉丝点击