Future和Callable的使用总结

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

Future和Callable的使用总结
在默认的情况下,线程Thread对象不具有返回值的功能,如果在需要取得返回值的情况下是极为不方便的,但在Java1.5的并发包中可以使用Future和Callable来使线程具有返回值的功能。

1.Future和Callable的介绍
接口Callable与线程功能密不可分,但和Runnable的主要区别为:
(1) 接口Callable的call()方法可以有返回值,但Runnable接口的run()方法没有返回值。

(2) Callable接口的call()方法可以声明抛出异常,而Runnable接口的run()方法不可以声明抛出异常。

执行完Callable接口中的任务后,返回值是通过Future接口进行获得的。

2.方法get()结合ExecutorService中的submit(Callable<T>)的使用
方法submit(Callable<T>)可以执行参数为Callable的任务,方法get()用于获得返回值,示例如下:
1.package mycallable;
2.
3.import java.util.concurrent.Callable;
4.
5.public class MyCallable implements Callable<String> {
6.
7.private int age;
8.
9.public MyCallable(int age) {
10.super();
11.this.age = age;
12.}
13.
14.public String call() throws Exception {
15.Thread.sleep(8000);
16.return "返回值年龄是:" + age;
17.}
18.
19.}
1.package test.run;
2.
3.import java.util.concurrent.ExecutionException;
4.import java.util.concurrent.Future;
5.import java.util.concurrent.LinkedBlockingDeque;
6.import java.util.concurrent.ThreadPoolExecutor;
7.import java.util.concurrent.TimeUnit;
8.
9.import mycallable.MyCallable;
10.
11.public class Run {
12.
13.public static void main(String[] args) throws InterruptedException {
14.try {
15.MyCallable callable = new MyCallable(100);
16.
17.ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 3, 5L,
18.TimeUnit.SECONDS, new LinkedBlockingDeque());
19.Future<String> future = executor.submit(callable);
20.System.out.println("main A " + System.currentTimeMillis());
21.System.out.println(future.get());
22.System.out.println("main B " + System.currentTimeMillis());
23.} catch (ExecutionException e) {
24. e.printStackTrace();
25.}
26.}
27.}
3.方法get()结合ExecutorService中的submit(Runnable)和isDone()的使用
方法submit()不仅可以传入Callable对象,也可以传入Runnable对象,说明submit方法支持有返回值和无返回值的功能。

如果submit方法传入Callable接口则可以有返回值,如果传入Runnable则无返回值,打印的结果就是null。

方法get()具有阻塞特性,而isDone()方法无阻塞特性。

1.package test.run;
2.
3.import java.util.concurrent.ExecutionException;
4.import java.util.concurrent.ExecutorService;
5.import java.util.concurrent.Executors;
6.import java.util.concurrent.Future;
7.
8./**
9.* 如果submit方法传入Callable接口则可以有返回值,如果传入Runnable则无返回值,打印的结果就是null。

方法get()具有阻塞特性,而isDone()方法无阻塞特性
10.* @author linhaiy
11.* @date 2019.03.06
12.*/
13.public class Run {
14.
15.public static void main(String[] args) {
16.try {
17.Runnable runnable = new Runnable() {
18.@Override
19.public void run() {
20.System.out.println("打印的信息");
21.}
22.};
23.ExecutorService executorRef = Executors.newCachedThreadPool();
24.Future future = executorRef.submit(runnable);
25.System.out.println(future.get() + " " + future.isDone());
26.} catch (InterruptedException e) {
27. e.printStackTrace();
28.} catch (ExecutionException e) {
29. e.printStackTrace();
30.}
31.}
32.}
4.使用ExecutorService接口中的方法submit(Runnable,T result)
方法submit(Runnable,T result)的第2个参数result可以作为执行结果的返回值,而不需要使用get()方法来进行获得。

1.package entity;
2.
3.public class Userinfo {
4.
5.private String username;
6.private String password;
8.public Userinfo() {
9.super();
10.}
11.
12.public Userinfo(String username, String password) {
13.super();
ername = username;
15.this.password = password;
16.}
17.
18.public String getUsername() {
19.return username;
20.}
21.
22.public void setUsername(String username) {
ername = username;
24.}
25.
26.public String getPassword() {
27.return password;
28.}
29.
30.public void setPassword(String password) {
31.this.password = password;
32.}
33.
34.}
1.package myrunnable;
3.import erinfo;
4.
5.public class MyRunnable implements Runnable {
6.
7.private Userinfo userinfo;
8.
9.public MyRunnable(Userinfo userinfo) {
10.super();
erinfo = userinfo;
12.}
13.
14.@Override
15.public void run() {
erinfo.setUsername("usernameValue");
erinfo.setPassword("passwordValue");
18.}
19.}
1.package test;
2.
3.import java.util.concurrent.ExecutionException;
4.import java.util.concurrent.Future;
5.import java.util.concurrent.FutureTask;
6.import java.util.concurrent.LinkedBlockingDeque;
7.import java.util.concurrent.ThreadPoolExecutor;
8.import java.util.concurrent.TimeUnit;
9.
10.import myrunnable.MyRunnable;
11.import erinfo;
12.
13.public class Test {
14.
15.FutureTask abc; //接口Future的实现类
16.
17.public static void main(String[] args) {
18.try {
erinfo userinfo = new Userinfo();
20.MyRunnable myrunnable = new MyRunnable(userinfo);
21.
22.ThreadPoolExecutor pool = new ThreadPoolExecutor(10, 10, 10,
23.TimeUnit.SECONDS, new LinkedBlockingDeque<Runnable>());
24.Future<Userinfo> future = pool.submit(myrunnable, userinfo);
25.System.out.println(future);
26.System.out.println("begin time=" + System.currentTimeMillis());
erinfo = future.get();
28.System.out.println("get value " + userinfo.getUsername() + " "
29.+ userinfo.getPassword());
30.System.out.println(" end time=" + System.currentTimeMillis());
31.} catch (InterruptedException e) {
32. e.printStackTrace();
33.} catch (ExecutionException e) {
34. e.printStackTrace();
35.}
36.}
37.}
5.方法cancel(boolean mayInterruptIfRunning) 和isCancelled()的使用
方法cancel(boolean mayInterruptIfRunning)的参数mayInterruptIfRunning的作用是:如果线程正在运行则是否中断正在运行的线程,在代码中需要使用if(Thread.currentThread().isInterrupted())进行配合。

方法cancel()的返回值代表发送取消任务的命令是否成功完成。

6.方法get(long timeout,TimeUnit unit)的使用
方法get(long timeout,TimeUnit unit)的作用是在指定的最大时间内等待获得返回值。

1.package mycallable;
2.
3.import java.util.concurrent.Callable;
4.
5.public class MyCallable implements Callable<String> {
6.public String call() throws Exception {
7.Thread.sleep(10000); //目的是为了在指定时间内获取不到返回值
8.System.out.println("sleep 10秒执行完了!");
9.return "anyString";
10.}
11.}
1.package test.run;
2.
3.import java.util.concurrent.ExecutionException;
4.import java.util.concurrent.Future;
5.import java.util.concurrent.LinkedBlockingDeque;
6.import java.util.concurrent.ThreadPoolExecutor;
7.import java.util.concurrent.TimeUnit;
8.import java.util.concurrent.TimeoutException;
9.
10.import mycallable.MyCallable;
11.
12.public class Run {
13.
14.public static void main(String[] args) {
15.try {
16.MyCallable callable = new MyCallable();
17.ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 3, 5L,
18.TimeUnit.SECONDS, new LinkedBlockingDeque());
19.System.out.println("begin " + System.currentTimeMillis());
20.Future<String> future = executor.submit(callable);
21.System.out.println("返回值" + future.get(5, TimeUnit.SECONDS));
22.System.out.println(" end " + System.currentTimeMillis());
23.} catch (InterruptedException e) {
24.System.out.println("进入catch InterruptedException");
25. e.printStackTrace();
26.} catch (ExecutionException e) {
27.System.out.println("进入catch ExecutionException");
28. e.printStackTrace();
29.} catch (TimeoutException e) {
30.System.out.println("进入catch TimeoutException");
31. e.printStackTrace();
32.}
33.}
34.}
7.自定义拒绝策略RejectedExecutionHandler接口的使用
接口RejectedExecutionHandler的主要作用是当线程池关闭后依然有任务要执行时,可以实现一些处理。

1.package com.executionhandler;
2.
3.import java.util.concurrent.FutureTask;
4.import java.util.concurrent.RejectedExecutionHandler;
5.import java.util.concurrent.ThreadPoolExecutor;
6.
7.public class MyRejectedExecutionHandler implements RejectedExecutionHandler {
8.public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
9.System.out.println(((FutureTask) r).toString() + " 被拒绝!");
10.}
11.}
1.package com.executionhandler;
2.
3.public class MyRunnable implements Runnable {
4.
5.private String username;
6.
7.public MyRunnable(String username) {
8.super();
ername = username;
10.}
11.
12.public void run() {
13.System.out.println(username + " 在运行!");
14.}
15.}
1.package com.executionhandler;
2.
3.import java.util.concurrent.ExecutorService;
4.import java.util.concurrent.Executors;
5.import java.util.concurrent.ThreadPoolExecutor;
6.
7.public class Run {
8.
9.public static void main(String[] args) {
10.
11.ExecutorService service = Executors.newCachedThreadPool();
12.ThreadPoolExecutor executor = (ThreadPoolExecutor) service;
13.executor.setRejectedExecutionHandler(new MyRejectedExecutionHandler());
14.service.submit(new MyRunnable("A"));
15.service.submit(new MyRunnable("B"));
16.service.submit(new MyRunnable("C"));
17.executor.shutdown();
18.service.submit(new MyRunnable("D"));
19.
20.}
21.}
8.方法execute()与submit()的区别
(1) 方法execute()没有返回值,而submit()方法可以有返回值。

(2) 方法execute()在默认的情况下异常直接抛出,不能捕获,但可以通过自定义ThreadFactory的方式进行捕获,而submit()方法在默认的情况下,可以catch Execution-Exeception捕获异常
9.验证Future的缺点
1.package mycallable;
2.
3.import java.util.concurrent.Callable;
4.
5.public class MyCallable implements Callable<String> {
6.
7.private String username;
8.private long sleepValue;
9.
10.public MyCallable(String username, long sleepValue) {
11.super();
ername = username;
13.this.sleepValue = sleepValue;
14.}
15.
16.@Override
17.public String call() throws Exception {
18.System.out.println(username);
19.Thread.sleep(sleepValue);
20.return "return " + username;
21.}
22.}
1.package test;
2.
3.import java.util.ArrayList;
4.import java.util.List;
5.import java.util.concurrent.Callable;
6.import java.util.concurrent.ExecutionException;
7.import java.util.concurrent.Future;
8.import java.util.concurrent.LinkedBlockingDeque;
9.import java.util.concurrent.ThreadPoolExecutor;
10.import java.util.concurrent.TimeUnit;
11.
12.import mycallable.MyCallable;
13.
14.public class Test {
15.
16.public static void main(String[] args) {
17.try {
18.MyCallable callable1 = new MyCallable("username1", 5000);
19.MyCallable callable2 = new MyCallable("username2", 4000);
20.MyCallable callable3 = new MyCallable("username3", 3000);
21.MyCallable callable4 = new MyCallable("username4", 2000);
22.MyCallable callable5 = new MyCallable("username5", 1000);
23.
24.List<Callable> callableList = new ArrayList<Callable>();
25.callableList.add(callable1);
26.callableList.add(callable2);
27.callableList.add(callable3);
28.callableList.add(callable4);
29.callableList.add(callable5);
30.
31.List<Future> futureList = new ArrayList<Future>();
32.
33.ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 10, 5, TimeUnit.SECONDS,
34.new LinkedBlockingDeque<Runnable>());
35.for (int i = 0; i < 5; i++) {
36.futureList.add(executor.submit(callableList.get(i)));
37.}
38.System.out.println("run first time= " + System.currentTimeMillis());
39.for (int i = 0; i < 5; i++) {
40.System.out.println(futureList.get(i).get() + " " + System.currentTimeMillis());
41.}
42.// 按顺序打印的效果
43.// 说明一个Future对应指定的一个Callable
44.} catch (InterruptedException e) {
45. e.printStackTrace();
46.} catch (ExecutionException e) {
47. e.printStackTrace();
48.}
49.}
50.}
总结:Future和Callable这两个接口的优点就是从线程中返回数据以便进行后期的处理,但是FutureTask类也有其自身的缺点,就是阻塞性。

相关文档
最新文档