两个例子解释Callable 和 Future接口

简介: 两个例子解释Callable 和 Future接口

Callable和Future接口,一个产生结果,一个拿到结果。Callable接口类似于Runnable,从名字就可以看出来了,但是Runnable不会返回结果,并且无法抛出返回结果的异常,而Callable功能更强大一些,被线程执行后,可以返回值,这个返回值可以被Future拿到,也就是说,Future可以拿到异步执行任务的返回值,下面来看一个简单的例子: FutureTask实现了两个接口,Runnable和Future,所以它既可以作为Runnable被线程执行,又可以作为Future得到Callable的返回值,那么这个组合的使用有什么好处呢?假设有一个很耗时的返回值需要计算,并且这个返回值不是立刻需要的话,那么就可以使用这个组合,用另一个线程去计算返回值,而当前线程在使用这个返回值之前可以做其它的操作,等到需要这个返回值时,再通过Future得到。 Callable是类似于Runnable的接口,实现Callable接口的类和实现Runnable的类都是可被其它线程执行的任务。Callable和Runnable有几点不同:

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

Callable的任务执行后可返回值,而Runnable的任务是不能返回值的。

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类实现了Callable,String将是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抛出的异常


作者:zhulin1028

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

相关文章
|
5月前
|
存储 Java
高并发编程之多线程锁和Callable&Future 接口
高并发编程之多线程锁和Callable&Future 接口
69 1
|
5月前
|
Java
JAVA JUC Callable 接口
【1月更文挑战第5天】JAVA JUC Callable 接口
|
2月前
|
并行计算 Java 大数据
Callable和Future
Callable和Future
|
4月前
|
存储 Java
详细解读Callable接口及Futrue接口详解
详细解读Callable接口及Futrue接口详解
16 0
|
5月前
面试官:除了继承Thread类和实现Runnable接口,你知道使用Callable接口的方式来创建线程吗?
面试官:除了继承Thread类和实现Runnable接口,你知道使用Callable接口的方式来创建线程吗?
37 0
面试官:除了继承Thread类和实现Runnable接口,你知道使用Callable接口的方式来创建线程吗?
|
5月前
|
Java 程序员
Java多线程基础-16:简述Java并发编程JUC中的Callable接口
Callable接口是Java中用于描述带有返回值任务的接口,与Runnable相对,后者无返回值。Callable的call()方法用于执行具体任务并返回结果。
71 0
|
5月前
|
Java
Java并发编程:理解并使用Future和Callable接口
【2月更文挑战第25天】 在Java中,多线程编程是一个重要的概念,它允许我们同时执行多个任务。然而,有时候我们需要等待一个或多个线程完成,然后才能继续执行其他任务。这就需要使用到Future和Callable接口。本文将深入探讨这两个接口的用法,以及它们如何帮助我们更好地管理多线程。
|
5月前
|
Java
创建线程的三种方式:继承Thread、Runnable 接口、Callable 接口
创建线程的三种方式:继承Thread、Runnable 接口、Callable 接口
|
5月前
|
Java 程序员
【JavaEE初阶】 Callable 接口
【JavaEE初阶】 Callable 接口
|
5月前
|
Java
多线程创建方式三 - 实现Callable接口
多线程创建方式三 - 实现Callable接口
42 1