How to do it...

Follow these steps to implement the example:

  1. Create a class named DocumentMock. It will generate a string matrix that will simulate a document:
        public class DocumentMock { 
  1. Create an array of strings with some words. This array will be used in the generation of the strings matrix:
        private String words[]={"the","hello","goodbye","packt",
"java","thread","pool","random",
"class","main"};
  1. Implement the generateDocument() method. It receives as parameters the number of lines, the number of words per line, and the word the example is going to look for. It returns a matrix of strings:
        public String[][] generateDocument(int numLines, int numWords,
String word){
  1. First, create the necessary objects to generate the document-the String matrix and a Random object to generate random numbers:
        int counter=0; 
String document[][]=new String[numLines][numWords];
Random random=new Random();
  1. Fill the array with strings. Store in each position the string that is at a random position in the array of words and count the number of appearances of the word the program will look for in the generated array. You can use this value to check whether the program does its job properly:
        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++;
}
}
}
  1. Write a message with the number of appearances of the word and return the matrix generated:
        System.out.println("DocumentMock: The word appears "+ counter+"
times in the document");
return document;
  1. Create a class named DocumentTask and specify that it extends the RecursiveTask class parameterized with the Integer class. This class will implement the task that will calculate the number of appearances of the word in a set of lines:
        public class DocumentTask extends RecursiveTask<Integer> { 
  1. Declare a private String matrix named document and two private int attributes named start and end. Also, declare a private String attribute named word:
        private String document[][]; 
private int start, end;
private String word;
  1. Implement the constructor of the class to initialize all its attributes:
        public DocumentTask (String document[][], int start, int end,
String word){
this.document=document;
this.start=start;
this.end=end;
this.word=word;
}
  1. Implement the compute() method. If the difference between the end and start attributes is smaller than 10, the task calculates the number of appearances of a word in the lines between those positions by calling the processLines() method:
        @Override 
protected Integer compute() {
Integer result=null;
if (end-start<10){
result=processLines(document, start, end, word);
  1. Otherwise, divide the group of lines into two objects, create two new DocumentTask objects to process those two groups, and execute them in the pool using the invokeAll() method:
        } 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);
  1. Then, add the values returned by both the tasks using the groupResults() method. Finally, return the result calculated by the task:
          try { 
result=groupResults(task1.get(),task2.get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
return result;
  1. Implement the processLines() method. It receives the string matrix, the start attribute, the end attribute, and the word attribute the task is searching for as parameters:
        private Integer processLines(String[][] document, int start,
int end,String word) {
  1. For every line the task has to process, create a LineTask object to process the complete line and store them in a list of tasks:
        List<LineTask> tasks=new ArrayList<LineTask>(); 
for (int i=start; i<end; i++){
LineTask task=new LineTask(document[i], 0,
document[i].length, word);
tasks.add(task);
}
  1. Execute all the tasks in that list using the invokeAll() method:
        invokeAll(tasks); 
  1. Sum the value returned by all these tasks and return the result:
        int result=0; 
for (int i=0; i<tasks.size(); i++) {
LineTask task=tasks.get(i);
try {
result=result+task.get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
return result;
  1. Implement the groupResults() method. It adds two numbers and returns the result:
        private Integer groupResults(Integer number1,Integer number2) { 
Integer result;
result=number1+number2;
return result;
}
  1. Create a class named LineTask and specify that it extends the RecursiveTask class parameterized with the Integer class. This class will implement the task that will calculate the number of appearances of the word in a line:
        public class LineTask extends RecursiveTask<Integer>{ 
  1. Declare a private String array attribute named line and two private int attributes named start and end. Finally, declare a private String attribute named word:
        private String line[]; 
private int start, end;
private String word;
  1. Implement the constructor of the class to initialize all its attributes:
        public LineTask(String line[],int start,int end,String word) { 
this.line=line;
this.start=start;
this.end=end;
this.word=word;
}
  1. Implement the compute() method of the class. If the difference between the end and start attributes is smaller than 100, the task searches for the word in the fragment of the line determined by the start and end attributes using the count() method:
        @Override 
protected Integer compute() {
Integer result=null;
if (end-start<100) {
result=count(line, start, end, word);
  1. Otherwise, divide the group of words in the line in two, create two new LineTask objects to process those two groups, and execute them in the pool using the invokeAll() method:
        } 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);
  1. Then, add the values returned by both the tasks using the groupResults() method. Finally, return the result calculated by the task:
          try { 
result=groupResults(task1.get(),task2.get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
return result;
  1. Implement the count() method. It receives the string array with the complete line, the start attribute, the end attribute, and the word attribute the task is searching for as parameters:
        private Integer count(String[] line, int start, int end,
String word) {
  1. Compare the words stored in the positions between the start and end attributes with the word attribute the task is searching for, and if they are equal, increment the counter variable:
        int counter; 
counter=0;
for (int i=start; i<end; i++){
if (line[i].equals(word)){
counter++;
}
}
  1. To slow the execution of the example, put the task to sleep for 10 milliseconds:
        try { 
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
  1. Return the value of the counter variable:
        return counter; 
  1. Implement the groupResults() method. It sums two numbers and returns the result:
        private Integer groupResults(Integer number1,Integer number2) { 
Integer result;
result=number1+number2;
return result;
}
  1. Implement the main class of the example by creating a class named Main with a main() method:
        public class Main{ 
public static void main(String[] args) {
  1. Create Document with 100 lines and 1000 words per line using the DocumentMock class:
        DocumentMock mock=new DocumentMock(); 
String[][] document=mock.generateDocument(100, 1000, "the");
  1. Create a new DocumentTask object to update the products of the entire document. The start parameter takes the value 0 and the end parameter takes the value 100:
        DocumentTask task=new DocumentTask(document, 0, 100, "the"); 
  1. Get the default ForkJoinPool executor using the commmonPool() method and execute the task on it using the execute() method:
        ForkJoinPool commonPool=ForkJoinPool.commonPool(); 
commonPool.execute(task);
  1. Implement a block of code that shows information about the progress of the pool, writing every second to the console the value of some parameters of the pool until the task finishes its execution:
        do { 
System.out.printf("*************************
***************** ");
System.out.printf("Main: Active Threads: %d ",
commonPool.getActiveThreadCount());
System.out.printf("Main: Task Count: %d ",
commonPool.getQueuedTaskCount());
System.out.printf("Main: Steal Count: %d ",
commonPool.getStealCount());
System.out.printf("***********************************
******* ");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
} while (!task.isDone());
  1. Shut down the pool using the shutdown() method:
        pool.shutdown(); 
  1. Wait for the finalization of the tasks using the awaitTermination() method:
        try { 
pool.awaitTermination(1, TimeUnit.DAYS);
} catch (InterruptedException e) {
e.printStackTrace();
}
  1. Write the number of the appearances of the word in the document. Check that this number is the same as the number written by the DocumentMock class:
        try { 
System.out.printf("Main: The word appears %d in the
document",task.get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.133.156.251