Java7线程学习笔记(五)

来源:互联网 发布:linux vim注释 编辑:程序博客网 时间:2024/05/16 07:03

Fork/Join框架:分解合并框架。

简介:是用来解决能够通过分治技术将问题拆分成小任务的问题。在一个任务中,先检查将要解决问题的大小,如果大于一个设定的大小,那就将问题拆分成可以通过框架来执行的小任务,如果问题的大小比设定的大小要小,就可以直接在任务里解决这个问题,然后根据 需要返回任务的结果。
没有固定的公式决定问题的参考大小,从而决定一个任务是需要进行拆分或不需要拆分。可以使用在任务中将要处理的元素的数目和任务执行所需要的时间决定参考大小。
Fork/Join基于以下两种操作:
分解(Fork)操作:当需要将一个任务拆分成更小的多个任务时,在框架中执行这些任务。
合并(Join)操作:当一个主任务等待其创建的多个子任务的完成执行。
Fork/join框架和执行器框架主要的区别在于工作窃取算法。与执行器框架不同,使用Join操作让一个主任务等到它所创建的子任务的完成,执行这个任务的线程称之为工作者线程。工作者线程寻找其他仍未被执行的任务,然后开始执行。通过这种方式,这些线程在运行时拥有所有的优点,进而提升应用程序的性能。
为了达到这个任务,通过Fork/join框架执行的任务有以下限制。

  • 任务只能使用fork()和join()操作当做同步机制,如果使用其他的同步机制。工作者线程就不能执行其他任务,当然这些任务是在同步操作里时。比如,如果在Fork/join框架中将一个任务休眠,正在执行这个任务的工作者线程在休眠期内不能执行另一个任务。
  • 任务不能执行I/O操作,比如文件数据的读取与写入。
  • 任务不能抛出非运行时异常,必须在代码里处理掉这些异常。

Fork/join框架的核心是由下列两个类组成的:

  • ForkJoinPool:这个类实现了ExecutorService接口和工作窃取算法。它管理工作者线程,并提供任务的状态信息,以及任务的执行信息。
  • ForkJoinTask:这个类是一个将在ForkJoinPool中执行的任务的基类。

Fork/join框架提供了一个任务里执行fork()和join()操作的机制和控制任务状态的方法。通常为了实现Fork/join任务,需要实现一个以下两个类之一的之类。

  • RecursiveAction:用于任务没有返回结果的场景。
  • RecursiveTask:用于任务有返回结果的场景。

创建Fork/join线程池:
当一个主任务执行两个或更多的子任务时,这个主任务将等待子任务的完成。用这种方法,执行主任务的线程称之为工作者线程,它将寻找其他的子任务来执行,并在子任务执行的时间里利用所有的线程优势。
使用无参数的类构造器创建了ForkJoinPool对象,因此他将执行默认的配置,创建一个线程数等于计算机cpu数目的线程池,创建好ForkJoinPool对象后,那些线程也就创建就绪了。调用invokeAll()方法来执行一个主任务所创建的多个子任务。这是一个同步调用,这个任务将等待子任务完成,然后继续执行(可能是结束)。当一个主任务等待他的子任务时,执行这个任务的工作者线程接受另一个等待执行的任务并开始执行。正因为有了这个行为,所以说Fork/join框架提供了一种比Runnable和Callable对象更加高效的任务管理机制。
ForkJoinTask类的invokeAll()方法是执行器框架(EcecutorFramework)和Fork/join框架之间的主要差异之一。在执行器框架中,所有的任务必须发送给执行器。
ForkJoinPool类仅在使用ForkJoinTask类时才使用工作窃取算法。
合并任务的结果:
Fork/join框架提供了执行任务并返回结果的能力。RecursiveTask类继承了ForkJoinTask类,并且实现了有执行器框架提供的Future接口。
异步运行任务:
在forkJoinPool中执行ForkJoinTask时,可以采用同步或异步方式。当采用同步方式执行时,发送任务给Fork/join线程池的方法直到任务执行完成后才会返回结果。而采用异步方式执行时,发送任务给执行器的方法将立即返回结果,但是任务仍能够继续执行。
当采用同步方式,调用这些方法(比如invokeAll())时,任务将被挂起,直到任务被发送到Fork/join线程池中执行完成。这种方式允许ForkJoinPool类采用工作窃取算法来分配一个新的任务给在执行休眠任务的工作者线程。相反当采用异步方法(比如fork()方法)时,任务加将继续执行,因此ForkJoinPool类无法使用工作窃取算法来提升应用程序性能。
Get()方法和Join()方法的区别:
Get():如果ForkJoinTask类执行结束,或者一直等到结束,那么get()方法的这个版本则返回由computer()方法返回的结果。
Join():join()方法不能被中断,如果中断调用join()方法的线程,方法将抛出InterruptedException异常。
如果任务抛出任何运行时异常,那么get()方法将返回ExecutionException异常,但是join()方法将返回润timeException异常。
取消任务:
在ForkJoinPool类中执行ForkjoinTask对象时,在任务开始执行前可以取消它。ForkJoinTask类提供了cancel()方法达到取消任务的目的,在取消一个任务的时候要注意以下两点:

  • ForkJoinPool类不提供任何方法来取消线程池中正在运行或者等待运行额所有任务。
  • 取消任务时,不能取消已经被执行的任务。
0 0