Java7提供了Fork/Join用于并行执行任务的框架, 可以把一个大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架。
如果一个应用能被分解成多个子任务,并且组合多个子任务的结果就能够获得最终的答案,那么这个应用就适合用 Fork/Join 模式来解决,对开发来说也不再需要处理各种并行相关事务,例如同步、通信、死锁等问题,需要做的就是拆分任务并组合每个子任务的中间结果。
JDK1.7引入的Fork/Join框架就是基于工作窃取算法,是指某个线程从其他队列里窃取任务来执行。工作窃取算法的优点是充分利用线程进行并行计算,并减少了线程间的竞争,其缺点是在某些情况下还是存在竞争,比如双端队列里只有一个任务时。并且消耗了更多的系统资源,比如创建多个线程和多个双端队列。
一般会使用双端队列,比如AB线程分别处理AB两个任务队列,当有一个线程执行完一个任务队列时,会去窃取另一个未完成的队列任务,而被窃取任务线程永远从双端队列的头部拿任务执行,而窃取任务的线程永远从双端队列的尾部拿任务执行。
在RecursiveTask类中最重要的是实现compute()接口,此处定义了计算和拆分方法。
fork() - 每个子任务在调用fork方法时,又会进入compute方法,如果还要拆分则继续递归调用。
CountDownLatch,又名发令枪。这个类能够使一个线程等待其他线程完成各自的工作后再执行。例如,应用程序的主线程希望在负责启动框架服务的线程已经启动所有的框架服务之后再执行。
CountDownLatch是通过一个计数器来实现的,计数器的初始值为线程的数量,每当一个线程完成了自己的任务后,计数器的值就会减1。当计数器值到达0时,它表示所有的线程已经完成了任务,然后在闭锁上等待的线程就可以恢复执行任务。
//参数count为计数值 public CountDownLatch(int count) { };
//调用await()方法的线程会被挂起,它会等待直到count值为0才继续执行 public void await() throws InterruptedException { }; //和await()类似,只不过等待一定的时间后count值还没变为0的话就会继续执行 public boolean await(long timeout, TimeUnit unit) throws InterruptedException{};
实现最大的并行性:有时想同时启动多个线程,实现最大程度的并行性。例如测试一个单例类,如果我们创建一个初始计数为1的CountDownLatch,并让所有线程都在这个锁上等待,那么我们可以很轻松地完成测试。我们只需调用 一次countDown()方法就可以让所有的等待线程同时恢复执行。
开始执行前等待n个线程完成各自任务(应用最广):例如应用程序启动类要确保在处理用户请求前,所有N个外部系统已经启动和运行了。
死锁检测:一个非常方便的使用场景是,你可以使用n个线程访问共享资源,在每次测试阶段的线程数目是不同的,并尝试产生死锁。
CyclicBarrier——回环栅栏,通过它可以实现让一组线程等待至某个状态之后再全部同时执行,叫做回环是因为当所有等待线程都被释放以后,CyclicBarrier可以被重用。
处理同一个动作有多个线程同时执行的场景,用一个栅栏卡在同一个状态,只有当所有线程抵达该状态了,才可以全部放行。
Semaphore可以控同时访问的线程个数,一个信号量有且仅有3种操作,且它们全部是原子的:初始化、增加和减少。其包含两个构造方法:
Java平台类库包含了丰富的并发基础构建模块,例如线程安全的容器类以及各种用于协调多个相互协作的线程控制流的同步工...
JAVA并发编程与高并发解决方案 - 并发编程 五 相关文章 JAVA并发编程与高并发解决方案 - 并发编程 一 ...
通过上一篇(JUC源码分析-线程池篇(四):ForkJoinPool - 1)的讲解,相信同学们对 ForkJoi...
如果不曾相遇 我也许不会这么伤心 如果不曾相识 也许我不会这么难过 如果不曾相知 也许我不会这么不舍 如果没有如果...
oneH小姐 H小姐和梁知分手一年后,H小姐还是单身。她总是在一个人闲暇时幻想和梁知重逢的桥段,北京说大也不大,也...

