1.Future和Callable的介绍

接口Callable与线程功能密不可分, 但和Runnable的主要区别为:
1) Callable接口的call() 方法可以有返回值, 而Runnable接口的run() 方法没有返回值。
2) Callable接口的call O方法可以声明抛出异常, 而Runnable接口的run() 方法不可以声明抛出异常。

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

2.方法get() 结合 Executor Service中的 submit(Callable) 的使用

方法submit(Callable) 可以执行参数为Callable的任务
方法get() 用于获得返回值。

  1. import java.util.concurrent.Callable;
  2. public class MyCallable implements Callable<String> {
  3. private int age;
  4. public MyCallable(int age) {
  5. this.age = age;
  6. }
  7. public String call() throws Exception {
  8. Thread.sleep(8000);
  9. return "age: " + age;
  10. }
  11. }

测试代码:

  1. import java.util.concurrent.*;
  2. public class Run {
  3. public static void main(String[] args) throws ExecutionException, InterruptedException {
  4. MyCallable callable = new MyCallable(10);
  5. ThreadPoolExecutor executor = new ThreadPoolExecutor(2,3,5L, TimeUnit.SECONDS, new LinkedBlockingDeque());
  6. Future<String> future = executor.submit(callable);
  7. System.out.println(future.get());
  8. }
  9. }

3.方法get() 结合Executor Service中的submit(Runnable) 和is Done) 的使用

方法submit() 不仅可以传人Callable对象, 也可以传入Runnable对象, 说明submit() 方法支持有返回值和无返回值的功能。

  1. public class Run1 {
  2. public static void main(String[] args) throws ExecutionException, InterruptedException {
  3. Runnable runnable = new Runnable() {
  4. @Override
  5. public void run() {
  6. System.out.println("print");
  7. }
  8. };
  9. ExecutorService executorService = Executors.newCachedThreadPool();
  10. Future future = executorService.submit(runnable);
  11. System.out.println(future.get() + " " + future.isCancelled());
  12. }
  13. }

4.使用ExecutorService接口中的方法submit(Runnable,T result)

方法submit(Runnable, T result) 的第2个参数result可以作为执行结果的返回值,而不需要使用get() 方法来进行获得。

Userinfo类:

  1. public class Userinfo {
  2. private String username;
  3. private String password;
  4. public Userinfo() {
  5. super();
  6. }
  7. public Userinfo(String username, String password) {
  8. super();
  9. this.username = username;
  10. this.password = password;
  11. }
  12. public String getUsername() {
  13. return username;
  14. }
  15. public void setUsername(String username) {
  16. this.username = username;
  17. }
  18. public String getPassword() {
  19. return password;
  20. }
  21. public void setPassword(String password) {
  22. this.password = password;
  23. }
  24. }

MyRunnable

  1. public class MyRunnable implements Runnable{
  2. private Userinfo userinfo;
  3. public MyRunnable(Userinfo userinfo) {
  4. super();
  5. this.userinfo = userinfo;
  6. }
  7. @Override
  8. public void run() {
  9. userinfo.setUsername("usernameValue");
  10. userinfo.setPassword("passwordValue");
  11. }
  12. }

Test:

  1. import java.util.concurrent.*;
  2. public class Test {
  3. FutureTask abc;
  4. public static void main(String[] args) throws ExecutionException, InterruptedException {
  5. Userinfo userinfo = new Userinfo();
  6. MyRunnable myRunnable = new MyRunnable(userinfo);
  7. ThreadPoolExecutor pool = new ThreadPoolExecutor(10,10,10, TimeUnit.SECONDS,
  8. new LinkedBlockingDeque<>());
  9. Future<Userinfo> future = pool.submit(myRunnable, userinfo);
  10. System.out.println("begin time=" + System.currentTimeMillis());
  11. userinfo = future.get();
  12. }
  13. }

5.方法 cancel(boolean may Interrupt If Running) 和is Cancelled O的使用

方法cancel(boolean mayInterruptIfRunning) 的参数mayInterruptIfRunning的作用是:如果线程正在运行则是否中断正在运行的线程, 在代码中需要使用if(Thread.currentThread) .isInterrupted() ) 进行配合。
方法cancel() 的返回值代表发送取消任务的命令是否成功完成。

6.方法get(longtime out, Time Unit unit) 的使用

方法get(longtime out, Time Unit unit) 的作用是在指定的最大时间内等待获得返回值。

7.异常处理

接口Callable任务在执行时有可能会出现异常, 那在Callable中异常是如何处理的呢?

8.自定义拒绝策略Rejected Execution Handler接口的使用

接口Rejected Execution Handler的主要作用是当线程池关闭后依然有任务要执行时, 可以实现一些处理。

9.方法execute() 与submit()的区别

方法execute() 没有返回值, 而submit() 方法可以有返回值。
方法execute() 在默认的情况下异常直接抛出, 不能捕获, 但可以通过自定义ThreadFactory的方式进行捕获, 而submit(方法在默认的情况下,可以catchExecutionException捕获异常。

10 Future的缺点

Callable接口与Runnable接口在对比时主要的优点是, Callable接口可以通过Future取得返回值。但需要注意的是, Future接口调用get() 方法取得处理的结果值时是阻塞性的, 也就是如果调用Future对象的get() 方法时, 任务尚未执行完成, 则调用get() 方法时一直阻塞到此任务完成时为止。如果是这样的效果, 则前面先执行的任务一旦耗时很多, 则后面的任务调用get() 方法就呈阻塞状态,也就是排队进行等待,大大影响运行效率。也就是主线程并不能保证首先获得的是最先完成任务的返回值, 这就是Future的缺点, 影响效率。