FutureTask

可用于异步获取执行结果或取消执行任务的场景。当一个计算任务需要执行很长时间,那么就可用 FutureTask 来封装该任务,主线程在完成自己的任务之后再去获取结果。

在介绍 Callable 时我们知道它可以有返回值,返回值通过 Future 进行封装。FutureTask 实现了 RunnableFuture 接口,该接口继承自 Runnable 和 Future 接口,这使得 FutureTask 既可以当做一个任务执行,也可以有返回值。

public class FutureTask<V> implements RunnableFuture<V>
public interface RunnableFuture<V> extends Runnable, Future<V>
public class FutureTaskExample {public static void main(String[] args) throws ExecutionException, InterruptedException {FutureTask<Integer> futureTask = new FutureTask<Integer>(new Callable<Integer>() {@Overridepublic Integer call() throws Exception {int result = 0;for (int i = 0; i < 100; i++) {Thread.sleep(10);result += i;}return result;}});Thread computeThread = new Thread(futureTask);computeThread.start();Thread otherThread = new Thread(() -> {System.out.println("other task is running...");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}});otherThread.start();System.out.println(futureTask.get());}
}

输出

other task is running...
4950

BlockingQueue

java.util.concurrent.BlockingQueue 接口有以下阻塞队列的实现:

  • FIFO 队列 :LinkedBlockingQueue、ArrayBlockingQueue(固定长度)
  • 优先级队列 :PriorityBlockingQueue

提供了阻塞的 take() 和 put() 方法:如果队列为空 take() 将阻塞,直到队列中有内容;如果队列为满 put() 将阻塞,直到队列有空闲位置。
使用 BlockingQueue 实现生产者消费者问题

public class ProducerConsumer {private static BlockingQueue<String> queue = new ArrayBlockingQueue<>(5);private static class Producer extends Thread {@Overridepublic void run() {try {queue.put("product");} catch (InterruptedException e) {e.printStackTrace();}System.out.print("produce..");}}private static class Consumer extends Thread {@Overridepublic void run() {try {String product = queue.take();} catch (InterruptedException e) {e.printStackTrace();}System.out.print("consume..");}}
}
public static void main(String[] args) {for (int i = 0; i < 2; i++) {Producer producer = new Producer();producer.start();}for (int i = 0; i < 5; i++) {Consumer consumer = new Consumer();consumer.start();}for (int i = 0; i < 3; i++) {Producer producer = new Producer();producer.start();}
}
produce..produce..consume..consume..produce..consume..produce..consume..produce..consume..

ForkJoin

主要用于并行计算中,和 MapReduce 原理类似,都是把大的计算任务拆分成多个小任务并行计算(类似于递归调用)。

public class ForkJoinExample extends RecursiveTask<Integer> {private final int threshold = 5;private int first;private int last;public ForkJoinExample(int first, int last) {this.first = first;this.last = last;}@Overrideprotected Integer compute() {int result = 0;if (last - first <= threshold) {// 任务足够小则直接计算for (int i = first; i <= last; i++) {result += i;}} else {// 拆分成小任务int middle = first + (last - first) / 2;ForkJoinExample leftTask = new ForkJoinExample(first, middle);ForkJoinExample rightTask = new ForkJoinExample(middle + 1, last);leftTask.fork();rightTask.fork();result = leftTask.join() + rightTask.join();}return result;}
}
public static void main(String[] args) throws ExecutionException, InterruptedException {ForkJoinExample example = new ForkJoinExample(1, 10000);ForkJoinPool forkJoinPool = new ForkJoinPool();Future result = forkJoinPool.submit(example);System.out.println(result.get());
}

ForkJoin 使用 ForkJoinPool 来启动,它是一个特殊的线程池,线程数量取决于 CPU 核数。

public class ForkJoinPool extends AbstractExecutorService

ForkJoinPool 实现了工作窃取算法来提高 CPU 的利用率。每个线程都维护了一个双端队列,用来存储需要执行的任务。工作窃取算法允许空闲的线程从其它线程的双端队列中窃取一个任务来执行。窃取的任务必须是最晚的任务,避免和队列所属线程发生竞争。例如下图中,Thread2 从 Thread1 的队列中拿出最晚的 Task1 任务,Thread1 会拿出 Task2 来执行,这样就避免发生竞争。但是如果队列中只有一个任务时还是会发生竞争。

J.U.C - 其它组件相关推荐

  1. 并发容器J.U.C -- AQS组件(一)

    AQS简介 AQS全名:AbstractQueuedSynchronizer,是并发容器J.U.C(java.lang.concurrent)下locks包内的一个类.它实现了一个FIFO的队列.底层 ...

  2. Java中J.U.C扩展组件之ForkJoinTask和ForkJoinPool

    Fork/Join框架中两个核心类ForkJoinTask与ForkJoinPool,声明ForkJoinTask后,将其加入ForkJoinPool中,并返回一个Future对象. ForkJoin ...

  3. Java中J.U.C扩展组件之Fork,join

    Fork/join介绍 Fork/join框架是java7提供的并行执行任务的框架,是把大任务分割成若干小任务,最后汇总若干小任务的执行结果得到最终的结果.它的思想与MapReduce类似.Fork把 ...

  4. 面试:你说你精通Java并发,给我讲讲Java并发之J.U.C

    转载自 面试:你说你精通Java并发,给我讲讲Java并发之J.U.C J.U.C J.U.C即java.util.concurrent包,为我们提供了很多高性能的并发类,可以说是java并发的核心. ...

  5. java库net2.0下载_visual j 2.0 下载-Visual J# 2.0(vjredist.exe)下载微软官方版-西西软件下载...

    visual j 2.0 下载vjredist.exe是Microsoft Visual J# 2.0的可再发行组件包和简体语言包,并非用于运行使用其他 Java 语言开发工具编写的应用程序,micr ...

  6. java 语言程序设计 李尊朝 第12章 Swing 组件

    早期的JDK版本中提供了Java抽象窗口工具集(Abstract Window Toolkit, AWT),其目的是为程序员创建图形用户界面提供支持,但是AWT功能有限,因此在后来的JDK版 本中,又 ...

  7. 针对上上篇博文--仿优酷菜单---的bug修改

    上一篇博文,有个小bug,就是点了后如果图片都隐藏了,此时再次点击那些按钮存在的位置时,还是会显示出来. 这里原因是图片隐藏了,但是图片的属性还在原来的位置,点击后还是会触发相应的方法,该怎么解决呢, ...

  8. AQS(CountdownLatch、CyclicBarrier、Semaphore)、FutureTask、BlockingQueue、ForkJoin

    1. J.U.C - AQS (AbstractQueuedSynchronizer) java.util.concurrent(J.U.C) 大大提高了并发性能,AQS 被认为是 J.U.C 的核心 ...

  9. Java集合篇:Vector

    一.Vector简介: (1)Vector可以实现可增长的对象数组.与数组一样,可以使用整数索引进行访问的组件.不过,Vector的大小是可以增加或者减小的,以便适应创建Vector后进行添加或者删除 ...

最新文章

  1. 快排递归非递归python_Python递归神经网络终极指南
  2. 【xamarin + MvvmCross 从零开始】六、模拟器的配置与连接
  3. 潘越云《面朝海子》:诗里的人都会终成眷属
  4. 青少年蓝桥杯_2020_steam考试_中级组_第五题
  5. 回顾 | Kubernetes SIG-Cloud-Provider-Alibaba 首次网研会(含 PPT 下载)
  6. GridFS删除文件代码示例
  7. android 带记忆功能的播放器源码,【全开源可二开】带后台管理面板的在线音乐播放器Android应用APP源码...
  8. guava的正确引入方式_使用Guava的AbstractInvocationHandler正确完成代理
  9. 字符串匹配算法(KMP)
  10. java 所有路径算法_经典算法题:二叉树的所有路径
  11. webpack常用知识点
  12. android获取详细地址,Android获取当前子网掩码地址(亲测可用)
  13. 翻译:where在Swift中的用法
  14. 中间人攻击的实践与原理(ARP毒化、DNS欺骗)
  15. 炒菜什么时候放盐最健康?
  16. 高中计算机 数制 教案,1.2.2 二进制与数制转换
  17. 使用 javaScript 编写倒计时小程序,到时提交表单
  18. 全球首发,国产开源「文本-视频生成」模型!免费在线体验,一键实现视频生成自由...
  19. 基于Android的学生学习打卡监督系统
  20. 〖经典怀念〗新白娘子传奇MV之青姐17部完整原版下载

热门文章

  1. C# winform以阅览模式打开PPT,并控制PPT上下页,轮播
  2. 【BZOJ-2400】Spoj839Optimal Marks 最小割 + DFS
  3. c++指针各种用法小结
  4. Box2DWeb_03之Shape
  5. java中子类继承父类时是否继承构造函数
  6. JZ50第一个只出现一次的字符JZ50第一个只出现一次的字符JZ25合并两个排序的链表思路
  7. 【孤偏盖全唐】Linux中find命令完整用法
  8. Linux服务器之间传输文件 scp命令
  9. python进阶18正则表达式
  10. BootstrapTable单元格宽度调整:colResizable()方法