在这个范例中,我们创建了ForkJoinPool对象,和一个将程池中执行的ForkJoinTask的子类。使用了无参的类构造器创建了ForkJoinPool对象,因此它将执行默认的配置。创建一个线程数等于计算机CPU数目的线程池,创建好ForkJoinPool对象之后,那些线程也创建就绪了,程池中等待任务的到达,然后开始执行。
由于Task类继承了RecursiveAction类,因此不返回结果。在本节,我们使用了推荐的结构来实现任务。如果任务需要更新大于10个产品,它将拆分这些元素为两部分,创建两个任务,并将拆分的部分相应地分配给新创建的任务。通过使用Task类的first和last属性,来获知任务将要更新的产品列表所在的位置范围。我们已经使用first和last属性,来操作产品列表中仅有的一份副本,而没有为每一个任务去创建不同的产品列表。
调用invokeAll()方法来执行一个主任务所创建的多个子任务。这是一个同步调用,这个任务将等待子任务完成,然后继续执行(也可能是结束)。当一个主任务等待它的子任务时,执行这个主任务的工作者线程接收另一个等待执行的任务并开始执行。正因为有了这个行为,所以说Fork/Join框架提供了一种比Runnable和Callable对象更加高效的任务管理机制。
ForkJoinTask类的invokeAll()方法是执行器框架(ExecutorFramework)和Fork/Join框架之间的主要差异之一。在执行器框架中,所有的任务必须发送给执行器,然而,在这个示例中,线程池中包含了待执行方法的任务,任务的控制也是程池中进行的。我们在Task类中使用了invokeAll()方法,Task类继承了RecursiveAction类,而RecursiveAction类则继承了ForkJoinTask类。
我们已经发送一个唯一的任务到线程池中,通过使用execute()方法来更新所有产品的列表。在这个示例中,它是一个同步调用,主线程一直等待调用的执行。
我们已经使用了ForkJoinPool类的一些方法,来检查正在运行的任务的状态和演变情况。这个类包含更多的方法,可以用于任务状态的检测。参见8.5节介绍的这些方法的完整列表。
最后,像执行器框架一样,必须调用shutdown()方法来结束ForkJoinPool的执行。
下面的截图展示了这个范例执行的部分结果。
可以看到,任务执行结束,并且产品的价格已经更新了。

ForkJoinPool类还提供了以下方法用于执行任务。
execute (Runnabletask):这是本范例中使用的execute()方法的另一种版本。这个方法发送一个Runnable任务给ForkJoinPool类。需要注意的是,使用Runnable对象时ForkJoinPool类就不采用工作窃取算法(Work-StealingAlgorithm),ForkJoinPool类仅在使用ForkJoinTask类时才采用工作窃取算法。
invoke(ForkJoinTasktask):正如范例所示,ForkJoinPool类的execute()方法是异步调用的,而ForkJoinPool类的invoke()方法则是同步调用的。这个方法直到传递进来的任务执行结束后才会返回。
也可以使用在ExecutorService类中声明的invokeAll()和invokeAny()方法,这些方法接收Callable对象作为参数。使用Callable对象时ForkJoinPool类就不采用工作窃取算法(Work-StealingAlgorithm),因此,最好使用执行器来执行Callable对象。
本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/jisuanjixue/article-40557-5.html
反而给中国扶持出强大的敌人
美国只想让所有主权国
辛苦了