Java 线程与并发研究系列二(实现Callable接口)

来源:互联网 发布:三国志9优化伴侣版本 编辑:程序博客网 时间:2024/05/30 23:13

通过实现Callable和Runnable接口都能够创建线程的执行体,但是Runnable接口并不返回任何值,如果你希望任务在完成的时候能够返回一个值

那么就可以通过实现Callable接口来实现。在JavaAPI中是这样描述Callable接口的:Callable和Runnable相似,他们的类实例都能够被其他Thread

执行,但是Callable接口能够返回一个值或者抛出一个异常,Runnable却不能,实现Callable接口需要重写其唯一的call()方法。

Callable接口是java 5新增加的接口,java5定义了Callable接口中的call()方法的返回类型为Future接口类型,并且java5为Future接口提供一个实现

类FutureTask,FutureTask 还实现了Runnable接口,由于Thread的执行体只接受Runnable接口实例,所以如果想Callable实例作为Thread的执行

体就必须通过FureTask来作为桥梁,即:正常情况下我们是将一个Runable接口实例设置进去(在这里这个实例即是FutureTask对象,因为

FutureTask实现了Runable接口,FutureTask对象即是Runnable接口的一个实例,而Callable接口实例的类型是Future类型,而FutureTask实现了

Future接口,所以Callable接口实例即相当于FutureTask实例:ps:其实不是,但是可以这样理解),下面看Callable接口实例作为Thread的执行体

的实现。

public class MyThread implements Callable<String>{@Overridepublic String call() throws Exception {String str = "史蒂芬森电话";System.out.println(str);return str;}public static void main(String[] args) {MyThread callable = new MyThread();//创建Callable接口实例FutureTask<String> futureTask = new FutureTask<>(callable);new Thread(futureTask).start();//其实就三步:1 创建Callable实例  //2将Callable实例设置进FutureTask实例中 //3将FutureTask实例作为Runnable类型设置进Thread中try {System.out.println("子线程的返回结果:"+futureTask.get());} catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();}}}

运行结果:

下面还介绍一种不通过FutureTask,来实现Callable实例作为线程的执行体

public class MyThread implements Callable<String>{int num;public MyThread(int num){this.num = num;}@Overridepublic String call() throws Exception {System.out.println(num);return "this task num is "+num;}public static void main(String[] args) {ExecutorService exec = Executors.newCachedThreadPool();List<Future<String>> list = new ArrayList<Future<String>>();for (int i = 0; i < 10; i++) {MyThread callable = new MyThread(i);//创建Callable接口实例list.add(exec.submit(callable));//将callable接口实例提交进线程池}for (Future<String>fs:list) {try {System.out.println(fs.get());} catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();}}exec.shutdown();}}

执行结果:

在这里还要注意一下,如果你将 exec.shutdown()注释掉,所有线程执行完毕,但是主线程还还没结束,这是因为线程池还没有关闭,导致主线程

无法结束,如果不注释掉,所有的线程执行完毕后,主线程也就自然结束了。

在上面的代码里我们会看到submit()方法会产生一个Future对象,你可以使用isDone方法来检查Future是否完成,当任务完成时,它会返回一个结果

你可以调用get()方法来获取该结果,如果任务还未完成就调用get()方法时,get()方法将阻塞,直至任务完成。

参考链接:http://www.cnblogs.com/liubingna/p/3401403.html

0 0