Java7引入了Fork Join的概念,来更好的支持并行运算。顾名思义,Fork Join类似与流程语言的分支,合并的概念。也就是说Java7 SE原生支持了在一个主线程中开辟多个分支线程,并且根据分支线程的逻辑来等待(或者不等待)汇集,当然你也可以fork的某一个分支线程中再开辟Fork Join,这也就可以实现Fork Join的嵌套。
有两个核心类ForkJoinPool和ForkJoinTask。
ForkJoinPool实现了ExecutorService接口,起到线程池的作用。所以他的用法和Executor框架的使用时一样的,当然Fork Join本身就是Executor框架的扩展。ForkJoinPool有3个关键的方法,来启动线程,execute(...),invoke(...),submit(...)。具体描述如下:
客户端非fork/join调用 | 内部调用fork/join | |
异步执行 | execute(ForkJoinTask) | ForkJoinTask.fork |
等待获取结果 | invoke(ForkJoinTask) | ForkJoinTask.invoke |
执行,获取Futrue | submit(ForkJoinTask) | ForkJoinTask.fork(ForkJoinTasks are Futures) |
ForkJoinTask是分支合并的执行任何,分支合并的业务逻辑使用者可以再继承了这个抽先类之后,在抽象方法exec()中实现。其中exec()的返回结果和ForkJoinPool的执行调用方(execute(...),invoke(...),submit(...)),共同决定着线程是否阻塞,具体请看下面的测试用例。
首先,用户需要创建一个自己的ForkJoinTask。代码如下:
- public class MyForkJoinTask<V> extends ForkJoinTask<V> {
- /**
- *
- */
- private static final long serialVersionUID = 1L;
- private V value;
- private boolean success = false;
- @Override
- public V getRawResult() {
- return value;
- }
- @Override
- protected void setRawResult(V value) {
- this.value = value;
- }
- @Override
- protected boolean exec() {
- System.out.println("exec");
- return this.success;
- }
- public boolean isSuccess() {
- return success;
- }
- public void setSuccess(boolean isSuccess) {
- this.success = isSuccess;
- }
- }
测试ForkJoinPool.invoke(...):
- @Test
- public void testForkJoinInvoke() throws InterruptedException, ExecutionException {
- ForkJoinPool forkJoinPool = new ForkJoinPool();
- MyForkJoinTask<String> task = new MyForkJoinTask<String>();
- task.setSuccess(true);
- task.setRawResult("test");
- String invokeResult = forkJoinPool.invoke(task);
- assertEquals(invokeResult, "test");
- }
- @Test
- public void testForkJoinInvoke2() throws InterruptedException, ExecutionException {
- final ForkJoinPool forkJoinPool = new ForkJoinPool();
- final MyForkJoinTask<String> task = new MyForkJoinTask<String>();
- new Thread(new Runnable() {
- public void run() {
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- }
- task.complete("test");
- }
- }).start();
- // exec()返回值是false,此处阻塞,直到另一个线程调用了task.complete(...)
- String result = forkJoinPool.invoke(task);
- System.out.println(result);
- }
- @Test
- public void testForkJoinSubmit() throws InterruptedException, ExecutionException {
- final ForkJoinPool forkJoinPool = new ForkJoinPool();
- final MyForkJoinTask<String> task = new MyForkJoinTask<String>();
- task.setSuccess(true); // 是否在此任务运行完毕后结束阻塞
- ForkJoinTask<String> result = forkJoinPool.submit(task);
- result.get(); // 如果exec()返回值是false,在此处会阻塞,直到调用complete
- }
测试ForkJoinPool.submit(...):
- @Test
- public void testForkJoinSubmit() throws InterruptedException, ExecutionException {
- final ForkJoinPool forkJoinPool = new ForkJoinPool();
- final MyForkJoinTask<String> task = new MyForkJoinTask<String>();
- task.setSuccess(true); // 是否在此任务运行完毕后结束阻塞
- ForkJoinTask<String> result = forkJoinPool.submit(task);
- result.get(); // 如果exec()返回值是false,在此处会阻塞,直到调用complete
- }
- @Test
- public void testForkJoinSubmit2() throws InterruptedException, ExecutionException {
- final ForkJoinPool forkJoinPool = new ForkJoinPool();
- final MyForkJoinTask<String> task = new MyForkJoinTask<String>();
- forkJoinPool.submit(task);
- Thread.sleep(1000);
- }
- @Test
- public void testForkJoinSubmit3() throws InterruptedException, ExecutionException {
- final ForkJoinPool forkJoinPool = new ForkJoinPool();
- final MyForkJoinTask<String> task = new MyForkJoinTask<String>();
- new Thread(new Runnable() {
- public void run() {
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- }
- task.complete("test");
- }
- }).start();
- ForkJoinTask<String> result = forkJoinPool.submit(task);
- // exec()返回值是false,此处阻塞,直到另一个线程调用了task.complete(...)
- result.get();
- Thread.sleep(1000);
- }
测试ForkJoinPool.execute(...):
- @Test
- public void testForkJoinExecute() throws InterruptedException, ExecutionException {
- ForkJoinPool forkJoinPool = new ForkJoinPool();
- MyForkJoinTask<String> task = new MyForkJoinTask<String>();
- forkJoinPool.execute(task); // 异步执行,无视task.exec()返回值。
- }