1. Callable

泛型接口,用于获取线程执行完的结果,Callable的声明如下

public interface Callable<V> {// 返回 V 类型的结果V call() throws Exception;
}

Callable 接口类似于Runnable,两者都是为那些其实例可能被另一个线程执行的类设计的。但是 Runnable 不会返回结果,并且无法抛出经过检查的异常,而Callable是可返回结果并且可以抛出异常的任务

public class MyCallable implements Callable{private int number;public MyCallable(int number) {this.number = number;}@Overridepublic Integer call() throws Exception {int sum = 0;for (int x = 1; x <= number; x++) {sum += x;}return sum;}
}public class CallableDemo {ExecutorService pool = Executors.newFixedThreadPool(2);Future<Integer> future = pool.submit(new SumCallable(10));Integer sum = future.get();pool.shutdown();class SumCallable implements Callable<Integer> {private int number;public SumCallable(int number){this.number = number;}@Overridepublic Integer call() throws Exception {int sum = 0;for (int i=0; i<number; i++){sum += i;}return sum;}}
}

2. Future

Future 为线程池提供了一个可管理的任务标准,它提供了对Runnable或Callable任务的执行结果进行取消、查询是否完成、获取结果、设置结果操作

Future 接口表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并获取计算的结果。计算完成后只能使用get()方法来获取结果,如有必要,计算完成前可以阻塞此方法

Future取得的结果类型和Callable返回的结果类型必须一致,这是通过泛型来实现的。Callable要采用ExecutorService的submit()方法提交,返回的future对象可以取消任务。Future声明如下

public interface Future<V> {boolean cancel(boolean var1);// 该任务是否已经取消boolean isCancelled();// 判断是否已经完成boolean isDone();// 获取结果,该方法会阻塞V get() throws InterruptedException, ExecutionException;// 获取结果,如果还未完成那么等待,直到timeout或返回结果,该方法会阻塞V get(long var1, TimeUnit var3) throws InterruptedException, ExecutionException, TimeoutException;
}

Future的简单使用

// 创建线程池对象
ExecutorService pool = Executors.newFixedThreadPool(2);
// 可以执行Runnable对象或者Callable对象代表的线程
Future<Integer> future = pool.submit(new MyCallable(100));
Integer i1 = future.get();
pool.shutdown();

Future常用方法

方法声明 功能描述
cancel() 取消任务
isCanceled() 任务是否取消
isDone() 任务是否完成
get() 获取结果,get()方法会阻塞,直到任务返回结果
set() 设置结果

3. FutureTask

Future只是定义了一些接口规范,而FutureTask则是它的实现类

public class FutureTask<V> implements RunnableFuture<V>{// 代码省略
}public interface RunnableFuture<V> extends Runnable, Future<V>{void run();
}

FutureTask会像Thread包装Runnable那样对Runnable和Callable进行包装,Runnable和Callable由构造函数注入

public FutureTask(Callable<V> callable) {if (callable == null)throw new NullPointerException();this.callable = callable;this.state = NEW;       // ensure visibility of callable
}
public FutureTask(Runnable runnable, V result) {this.callable = Executors.callable(runnable, result);this.state = NEW;       // ensure visibility of callable
}

由于FutureTask实现了Runnable,因此,它既可以通过Thread包装来直接执行,也可以提交给ExecuteService来执行,并且还可以直接通过get()方法获取执行结果,该方法会阻塞,直到结果返回。因此,FutureTask既是Future、Runnable,又是包装了Callable,它是两者的合体

public class FutureDemo {// 线程池static ExecutorService mExecutor = Executors.newSingleThreadExecutor();// main函数public static void main(String[] args) {try {futureWithRunnable();futureWithCallable();futureTask();} catch (Exception e) {}}/*** 其中Runnable实现的是void run()方法,无返回值;Callable实现的是 V* call()方法,并且可以返回执行结果。其中Runnable可以提交给Thread来包装下* ,直接启动一个线程来执行,而Callable则一般都是提交给ExecuteService来执行。*/private static void futureWithRunnable() throws InterruptedException, ExecutionException {// 提交runnable则没有返回值, future没有数据Future<?> result = mExecutor.submit(new Runnable() {@Overridepublic void run() {fibc(20);}});System.out.println("future result from runnable : " + result.get());}private static void futureWithCallable() throws InterruptedException, ExecutionException {/*** 提交Callable, 有返回值, future中能够获取返回值*/Future<Integer> result2 = mExecutor.submit(new Callable<Integer>() {@Overridepublic Integer call() throws Exception {return fibc(20);}});System.out.println("future result from callable : "+ result2.get());}private static void futureTask() throws InterruptedException, ExecutionException {/*** FutureTask则是一个RunnableFuture<V>,即实现了Runnbale又实现了Futrue<V>这两个接口,* 另外它还可以包装Runnable(实际上会转换为Callable)和Callable* <V>,所以一般来讲是一个符合体了,它可以通过Thread包装来直接执行,也可以提交给ExecuteService来执行* ,并且还可以通过v get()返回执行结果,在线程体没有执行完成的时候,主线程一直阻塞等待,执行完则直接返回结果。*/FutureTask<Integer> futureTask = new FutureTask<Integer>(new Callable<Integer>() {@Overridepublic Integer call() throws Exception {return fibc(20);}});// 提交futureTaskmExecutor.submit(futureTask);System.out.println("future result from futureTask : "+ futureTask.get());}// 效率底下的斐波那契数列, 耗时的操作private static int fibc(int num) {if (num == 0) {return 0;}if (num == 1) {return 1;}return fibc(num - 1) + fibc(num - 2);}
}

输出结果

future result from runnable : null
future result from Callable : 6765
future result from futureTask : 6765

4. CompletionService

CompletionService用于提交一组Callable任务,其take()方法返回已完成的一个Callable任务对应的Future对象。

示例:这里数据的获取好比同时种了好几块地的麦子,然后等待收割,秋收时,哪块先熟,先收割哪块

import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;  public class CallableAndFuture {  public static void main(String[] args){  //创建一个单独的线程         ExecutorService threadPool = Executors.newSingleThreadExecutor();  //future泛型与Callable的类型一致        Future<String> future = threadPool.submit(new Callable<String>(){  @Override  public String call() throws Exception {  Thread.sleep(3000);  return "hello";  }  });  System.out.println("等待結果……");  //在指定时timeout内等待,未等到抛出TimeoutException  //System.out.println("拿到结果:" + future.get(long timeout,TimeUnit unit));  try {  System.out.println("拿到结果:" + future.get()); //获取线程执行后的结果  } catch (InterruptedException e) {  e.printStackTrace();  } catch (ExecutionException e) {  e.printStackTrace();  }  //CompletionService用于提交一组Callable任务,  //其take方法返回已完成的一个Callable任务对应的Future对象。  ExecutorService threadPool2 = Executors.newFixedThreadPool(10);  CompletionService<Integer> completionService = new ExecutorCompletionService<Integer>(threadPool2);  //创建10任务  for(int i=1;i<=10;i++){  final int seq = i;  //将任务提交给线程池  completionService.submit(new Callable<Integer>(){  @Override  public Integer call() throws Exception {  Thread.sleep(new Random().nextInt(5000));  return seq;               }  });  }  //获取结果,哪个结果先返回就先获得  for(int i=0;i<10;i++){  try {  System.out.println(completionService.take().get());  } catch (InterruptedException e) {  e.printStackTrace();  } catch (ExecutionException e) {  e.printStackTrace();  }  }  }
}  

输出结果

等待結果……
拿到结果:hello
3
6
10
2
4
8
5
1
7
9

Java高并发编程:Callable、Future和FutureTask相关推荐

  1. Java高并发编程学习(三)java.util.concurrent包

    简介 我们已经学习了形成Java并发程序设计基础的底层构建块,但对于实际编程来说,应该尽可能远离底层结构.使用由并发处理的专业人士实现的较高层次的结构要方便得多.要安全得多.例如,对于许多线程问题,可 ...

  2. Java高并发编程 (马士兵老师视频)笔记(一)同步器

    本篇主要总结同步器的相关例子:包括synchronized.volatile.原子变量类(AtomicXxx).CountDownLatch.ReentrantLock和ThreadLocal.还涉及 ...

  3. Java高并发编程详解系列-Java线程入门

    根据自己学的知识加上从各个网站上收集的资料分享一下关于java高并发编程的知识点.对于代码示例会以Maven工程的形式分享到个人的GitHub上面.   首先介绍一下这个系列的东西是什么,这个系列自己 ...

  4. 29W 字总结阿里 Java 高并发编程:案例 + 源码 + 面试 + 系统架构设计

    下半年的跳槽季已经开始,好多同学已经拿到了不错的 Offer,同时还有一些同学对于 Java 高并发编程还缺少一些深入的理解,不过不用慌,今天老师分享的这份 27W 字的阿里巴巴 Java 高并发编程 ...

  5. @冰河老师的巨作,人手一册的Java高并发编程指南,值得了解一下

    还真不好意思,这次 Java Thread Pool 惊爆了! 高并发是每一个后端开发工程师都头疼的问题,也是工程师能力的分水岭.要想基于JDK核心技术,玩转高并发编程,必须要好好修炼内功才行. 文章 ...

  6. Java高并发编程:活跃性危险

    Java高并发程序中,不得不出现资源竞争以及一些其他严重的问题,比如死锁.线程饥饿.响应性问题和活锁问题.在安全性与活跃性之间通常存在依赖,我们使用加锁机制来确保线程安全,但是如果过度地使用加锁,则可 ...

  7. Java高并发编程详解系列-7种单例模式

    引言 在之前的文章中从技术以及源代码的层面上分析了关于Java高并发的解决方式.这篇博客主要介绍关于单例设计模式.关于单例设计模式大家应该不会陌生,作为GoF23中设计模式中最为基础的设计模式,实现起 ...

  8. Java高并发编程详解系列-Future设计模式

    导语   假设,在一个使用场景中有一个任务需要执行比较长的时间,通常需要等待任务执行结束之后或者是中途出错之后才能返回结果.在这个期间调用者只能等待,对于这个结果Future设计模式提供了一种凭据式的 ...

  9. Java高并发编程案例

    文章目录 synchronized关键字 对象加锁 修饰方法 锁定静态方法 同步和非同步方法同时调用 脏读 可重入锁 异常释放锁 同步监视器变化 volatile 线程之间的可见性 对比synchro ...

  10. Java高并发编程(八):Java并发容器和框架

    1. ConcurrentHashMap 1.1 ConcurrentHashMap的优势 在并发编程中使用HashMap可能导致程序死循环.而使用线程安全的HashTable效率又非 常低下,基于以 ...

最新文章

  1. 边城高级中学2021届高考成绩查询,湖南省花垣县边城高级中学2021届高三第二学期学科素养测试英语试题及答案.doc...
  2. Iframe自适应高度绝对好使的代码 兼容IE,遨游,火狐[转]
  3. C++后台服务程序开发模式
  4. Android WebView对https无响应
  5. OpenCV创建自己的corner检测器
  6. Pytorch教程(十八)tensor的保存为csv,并加载
  7. 如何量化技术团队的效能?
  8. 把第三方jar包放入本地仓库
  9. 外媒:微信小程序顺应“APP中启动APP”的行业潮流
  10. java之包装类与BigInteger、BigDecimal
  11. 前端安全 -- XSS攻击
  12. python中pep8规范_Python PEP8规范
  13. linux tomcat配置https
  14. CAS实现单点登录SSO执行原理探究超详细
  15. mysql书单推荐_MySQL零基础入门推荐书籍?
  16. 记一次windows系统主引导修复
  17. 单元测试--Mockito之spy
  18. 远程桌面链接怎么共享本地磁盘
  19. rstp edgeport
  20. 「Git」常用工作流介绍

热门文章

  1. 7个步骤,帮您轻松实现云迁移
  2. 【指标统计】删除失败遥控
  3. SpringMvc CharacterEncodingFilter 解析 encoding 参数并初始化参数
  4. Mariadb修改root密码
  5. javascript封装与多态的体现
  6. Runner站立会议08
  7. Android深度探索(卷1)HAL与驱动开发读后感---第四章
  8. Office2013插件开发Outlook篇(1)-- 第一个office2013插件
  9. [转载]IPhone之NSFileManager的使用
  10. AspNetDB.mdf数据库的建立和使用