java-forkjoin带有返回值

来自并发编程网: http://ifeve.com/fork-join-3/

如果这个任务必须解决一个超过预定义大小的问题,你应该将这个任务分解成更多的子任务,并且用Fork/Join框架来执行这些子任务。当这些子任务完成执行,发起的任务将获得所有子任务产生的结果 ,对这些结果进行分组,并返回最终的结果。最终,当在池中执行的发起的任务完成它的执行,你将获取整个问题地最终结果。

1, 生成二维数组模拟文档:

package com.wenbronk.forkjoin.withresult;

import java.util.Random;

/**
 * Created by wenbronk on 2017/7/26.
 */
public class Document {

    private String words[] = {"the", "hello", "goodbye", "pack", "java", "thread", "pool", "random", "class", "main"};

    public String[][] generateDocument(int numLines, int numWords, String word) {
        int counter = 0;
        String[][] document = new String[numLines][numWords];
        Random random = new Random();

        // 填充数组
        for (int i=0; i<numLines; i++){
            for (int j=0; j<numWords; j++) {
                int index=random.nextInt(words.length);
                document[i][j]=words[index];
                if (document[i][j].equals(word)){
                    counter++;
                }
            }
        }
        System.out.println(document.length + ": " + document[document.length - 1].length);

        System.out.println("DocumentMock: The word appears " + counter + " times in the document");
        return document;
    }

}

2, 对模拟文档的进行行拆分

package com.wenbronk.forkjoin.withresult;

import java.util.ArrayList;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.RecursiveTask;

/**
 * Created by wenbronk on 2017/7/26.
 */
public class DocumentTask extends RecursiveTask<Integer> {

    private String[][] document;
    private int start, end;
    private String word;

    public DocumentTask(String[][] document, int start, int end, String word) {
        this.document = document;
        this.start = start;
        this.end = end;
        this.word = word;
    }

    @Override
    protected Integer compute() {
        int result = 0;

        if (end - start < 10) {
            result = processLines(document, start, end, word);
        } else {
            int mid = (start + end) / 2;
            DocumentTask task1 = new DocumentTask(document, start, mid, word);
            DocumentTask task2 = new DocumentTask(document, mid, end, word);

            invokeAll(task1, task2);
            try {
                result = groupResults(task1.get(), task2.get());
            }catch (InterruptedException | ExecutionException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    private int groupResults(Integer integer, Integer integer1) {
        return integer + integer1;
    }

    /**
     * 要查找的单词
     */
    private int processLines(String[][] document, int start, int end, String word) {
        ArrayList<LineTask> tasks = new ArrayList<>();
        for (int i = start; i < end; i++) {
            LineTask lineTask = new LineTask(document[i], 0, document[i].length, word);
            tasks.add(lineTask);
        }

        invokeAll(tasks);
        int result = 0;
//        for (LineTask task : tasks) {
        for (int i = 0; i < tasks.size(); i++) {
            LineTask task = tasks.get(i);
            try {
//                Thread.sleep(100);
                result += task.get();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return result;
    }
}

3, 对行进行单词拆分

package com.wenbronk.forkjoin.withresult;

import java.util.concurrent.RecursiveTask;

/**
 * 统计单词在一行出现的次数
 * Created by wenbronk on 2017/7/27.
 */
public class LineTask extends RecursiveTask<Integer> {
    private static final long seriaVersionUID = 1L;
    private String[] line;
    private int start, end;
    private String word;

    public LineTask(String[] line, int start, int end, String word) {
        this.line = line;
        this.start = start;
        this.end = end;
        this.word = word;
    }

    @Override
    protected Integer compute() {
        Integer result = null;
        if (end - start < 100) {
            result = count(line, start, end, word);
        }else {
            int mid = (start + end) / 2;
            LineTask task1 = new LineTask(line, start, mid, word);
            LineTask task2 = new LineTask(line, mid, end, word);
            invokeAll(task1, task2);
            try {
                result = groupResult(task1.get(), task2.get());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    /**
     * 合并2个数值的值, 返回结果
     * @return
     */
    private Integer groupResult(Integer num1, Integer num2) {
        return num1 + num2;
    }

    /**
     * 查找行中出现word的次数
     */
    private Integer count(String[] line, int start, int end, String word) {
        int counter = 0;
        for (int i = start; i < end; i++) {
            if (word.equals(line[i])) {
                counter ++;
            }
        }
//        try {
//            Thread.sleep(10);
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
        return counter;
    }
}

4, 入口执行类

package com.wenbronk.forkjoin.withresult;

import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.TimeUnit;

/**
 * Created by wenbronk on 2017/7/27.
 */
public class CountMain {

    public static void main(String[] args) {
        Document document = new Document();
        String[][] documents = document.generateDocument(100, 1000, "random");

        DocumentTask task = new DocumentTask(documents, 0, 100, "random");
        ForkJoinPool pool = new ForkJoinPool();
        pool.execute(task);

        do {
            System.out.printf("******************************************\n");
            System.out.printf("Main: Parallelism: %d\n",pool.getParallelism());
            System.out.printf("Main: Active Threads: %d\n",pool.getActiveThreadCount());
            System.out.printf("Main: Task Count: %d\n",pool.getQueuedTaskCount());
            System.out.printf("Main: Steal Count: %d\n",pool.getStealCount());
            System.out.printf("******************************************\n");
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        } while (!task.isDone());

        pool.shutdown();

        try {
            System.out.printf("Main: The word appears %d in the document ", task.get());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
时间: 2024-11-05 06:12:47

java-forkjoin带有返回值的相关文章

在Java 线程中返回值的用法

http://icgemu.iteye.com/blog/467848 在Java 线程中返回值的用法 博客分类: Java Javathread 有时在执行线程中需要在线程中返回一个值:常规中我们会用Runnable接口和Thread类设置一个变量:在run()中改变变量的值,再用一个get方法取得该值,但是run何时完成是未知的:我们需要一定的机制来保证. 在在Java se5有个Callable接口:我们可以用该接口来完成该功能: 代码如: Java代码   package com.thr

Android JNI之调用JAVA方法的返回值签名

从http://blog.csdn.net/lonelyroamer/article/details/7932787截取的 如何签名: 下面看看Sign签名如何写,来表示要取得的属性或方法的类型. 1.普通类型签名 2.引用类型签名 object     L开头,然后以/ 分隔包的完整类型,后面再加:   比如说String    签名就是   Ljava/lang/String; Array      以[ 开头,在加上数组元素类型的签名            比如int[]   签名就是[I

Java线程中带有返回值的线程Callable

在Java5之前,线程是没有返回值的,常常为了“有”返回值,破费周折,而且代码很不好写.或者干脆绕过这道坎,走别的路了.现在Java终于有可返回值的任务(也可以叫做线程)了. 可返回值的任务必须实现Callable接口,类似的,无返回值的任务必须Runnable接口. 执行Callable任务后,可以获取一个Future的对象,在该对象上调用get就可以获取到Callable任务返回的Object了. 下面是个很简单的例子: package com.lyc import java.util.co

Java连载27-有返回值的方法注意点

一.方法注意点 (1)方法的调用不一定再main方法中,可以在其他方法中进行调用,只要是程序执行到的位置,都可以去调用其他方法. (2)方法调用的时候,实参和形参要求个数对应相同,数据类型对应相同,方法不同的时候,要求能够进行相应的自动类型转换 (3)当方法的调用和方法在同一个类中的时候,“类名.”是可以省略不写的. (4)建议在一个java文件中只定义一个类为好,不要定义多个类,这里只是举例,不建议模仿 例子: public class d27_{ public static void mai

java方法重写返回值类型

重写(Overriding)(1) 父类与子类之间的多态性,对父类的函数进行重新定义.如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写 (Overriding).在Java中,子类可继承父类中的方法,而不需要重新编写相同的方法.但有时子类并不想原封不动地继承父类的方法,而是想作一定的修改,这就需要采用方法的重写.方法重写又称方法覆盖.(2)若子类中的方法与父类中的某一方法具有相同的方法名.返回类型和参数表,则新方法将覆盖原有的方法.如需父类中原有的方法,可使用super关键字

带有返回值的线程Callable

在Java5之前,线程是没有返回值的,常常为了“有”返回值,破费周折,而且代码很不好写.或者干脆绕过这道坎,走别的路了.现在Java终于有可返回值的任务(也可以叫做线程)了. 可返回值的任务必须实现Callable接口,类似的,无返回值的任务必须Runnable接口. 执行Callable任务后,可以获取一个Future的对象,在该对象上调用get就可以获取到Callable任务返回的Object了. 下面是个很简单的例子: package com.lyc import java.util.co

带有返回值的 Callable 使用

工作中很多涉及到多线程的地方都implemnets Runable 接口 或者是 extends Thread 抽象类,但是这样子的话得不到返回值. 如果以下场景: 在多线程中计算值,线程结束后需要携带返回值. 这时就需要Callable接口,实现改接口后需要实现方法 call .改接口需要ExecutorService的submit方法执行,执行结果包装在 Future<?>泛型类中. 通过Future类的get()方法取得返回值,get()是阻塞的,在线程执行前调用get()方法会一直阻塞

10-02 Java 形式参数和返回值的问题深入研究,链式编程

形式参数和返回值的问题: 1:形式参数和返回值的问题(理解) (1)形式参数: 类名:需要该类的对象 抽象类名:需要该类的子类对象 接口名:需要该接口的实现类对象 (2)返回值类型: 类名:返回的是该类的对象 抽象类名:返回的是该类的子类对象 接口名:返回的是该接口的实现类的对象 (3)链式编程 对象.方法1().方法2().......方法n(); 这种用法:其实在方法1()调用完毕后,应该一个对象: 方法2()调用完毕后,应该返回一个对象. 方法n()调用完毕后,可能是对象,也可以不是对象.

Java 中无返回值的方法在使用时应该注意的问题

Java 中的方法是形态多样的.无返回值的方法在使用时应该规避哪些问题呢? 一.不可以打印调用或是赋值调用,只能是单独调用(非常重要): 二.返回值没有,不代表参数就没有: 三.不能return一个具体的值,否则会报错: 四.return分号可以直接省略: 五.无返回值方法应该使用类型void. 原文地址:https://www.cnblogs.com/yanglongbo/p/10981842.html

正确理解Java方法的返回值

首先来看一段代码 我们把这段代码称为代码①,接下来我们再来看另外一段代码 我们把这段代码称为代码②.在代码①当中,定义了一个方法,这个方法声明的返回值类型是double,而实际通过return关键字返回的却是一个int型的值,但并没有引起编译错误.而在代码②当中,情况正好相反,方法声明的返回值类型是int,方法内部的return关键字实际返回了一个double类型的值,在这种情况下,编译器却报出了语法错误.对比一下这两种情况,很多初学Java的小伙伴搞不清:为什么同样是方法声明的返回值类型与实际