JAVA并发编程 用法集合2 Callable和Future

来源:互联网 发布:网络格斗游戏大全 编辑:程序博客网 时间:2024/05/21 21:37

2Callable  Future接口

    Callable是类似于Runnable的接口,实现Callable接口的类和实现Runnable的类都是可被其它线程执行的任务。CallableRunnable有几点不同:

    Callable规定的方法是call(),而Runnable规定的方法是run().

    call()方法可抛出异常,而run()方法是不能抛出异常的。

    运行Callable任务可拿到一个Future对象,通过Future对象可了解任务执行情况,可取消任务的执行,还可获取任务执行的结果。

    以下是Callable的一个例子:

    public class DoCallStuff implements Callable{ // *1

            private int aInt;

            public DoCallStuff(int aInt) {

                    this.aInt = aInt;

            }

            public String call() throws Exception { //*2

                    boolean resultOk = false;

                    if(aInt == 0){

                            resultOk = true;

                    }  else if(aInt == 1){

                            while(true){ //infinite loop

                                    System.out.println("looping....");

                                    Thread.sleep(3000);

                            }

                    } else {

                            throw new Exception("Callable terminated with Exception!"); //*3

                    }

                    if(resultOk){

                            return "Task done.";

                    } else {

                            return "Task failed";

                    }

            }

    }

    *1: 名为DoCallStuff类实现了CallableString将是call方法的返回值类型。例子中用了String,但可以是任何Java类。

    *2: call方法的返回值类型为String,这是和类的定义相对应的。并且可以抛出异常。

    *3: call方法可以抛出异常,如加重的斜体字所示。

     

    以下是调用DoCallStuff的主程序。

    import java.util.concurrent.ExecutionException;

    import java.util.concurrent.ExecutorService;

    import java.util.concurrent.Executors;

    import java.util.concurrent.Future;

    public class Executor {

            public static void main(String[] args){

                    //*1

                    DoCallStuff call1 = new DoCallStuff(0);

                    DoCallStuff call2 = new DoCallStuff(1);

                    DoCallStuff call3 = new DoCallStuff(2);

                    //*2

                    ExecutorService es = Executors.newFixedThreadPool(3);

                    //*3

                    Future future1 = es.submit(call1);

                    Future future2 = es.submit(call2);

                    Future future3 = es.submit(call3);

                    try {

                            //*4

                            System.out.println(future1.get());

                             //*5

                            Thread.sleep(3000);

                            System.out.println("Thread 2 terminated? :" + future2.cancel(true));

                            //*6

                            System.out.println(future3.get());

                    } catch (ExecutionException ex) {

                            ex.printStackTrace();

                    } catch (InterruptedException ex) {

                            ex.printStackTrace();

                    }

            }

    }

     

    *1: 定义了几个任务

    *2: 初始了任务执行工具。任务的执行框架将会在后面解释。

    *3: 执行任务,任务启动时返回了一个Future对象,如果想得到任务执行的结果或者是异常可对这个Future对象进行操作。Future所含的值必须跟Callable所含的值对映,比如说例子中Future对印Callable

    *4: 任务1正常执行完毕,future1.get()会返回线程的值

    *5: 任务2在进行一个死循环,调用future2.cancel(true)来中止此线程。传入的参数标明是否可打断线程,true表明可以打断。

    *6: 任务3抛出异常,调用future3.get()时会引起异常的抛出。

     运行Executor会有以下运行结果:

    looping....

    Task done. //*1

    looping....

    looping....//*2

    looping....

    looping....

    looping....

    looping....

    Thread 2 terminated? :true //*3

    //*4

    java.util.concurrent.ExecutionException: java.lang.Exception: Callable terminated with Exception!

            at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:205)

            at java.util.concurrent.FutureTask.get(FutureTask.java:80)

            at concurrent.Executor.main(Executor.java:43)

            …….

    *1: 任务1正常结束

    *2: 任务2是个死循环,这是它的打印结果

    *3: 指示任务2被取消

    *4: 在执行future3.get()时得到任务3抛出的异常