1 apr 5, 2012 forkjoin new in java 7. incrementor i package helloworld; import...
TRANSCRIPT
![Page 1: 1 Apr 5, 2012 ForkJoin New in Java 7. Incrementor I package helloWorld; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.RecursiveTask;](https://reader036.vdocuments.mx/reader036/viewer/2022082820/56649e7b5503460f94b7d4fc/html5/thumbnails/1.jpg)
1Apr 5, 2012
ForkJoin
New in Java 7
![Page 2: 1 Apr 5, 2012 ForkJoin New in Java 7. Incrementor I package helloWorld; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.RecursiveTask;](https://reader036.vdocuments.mx/reader036/viewer/2022082820/56649e7b5503460f94b7d4fc/html5/thumbnails/2.jpg)
Incrementor I package helloWorld;
import java.util.concurrent.ForkJoinPool;import java.util.concurrent.RecursiveTask;
2
The first thing you need to do is to import some classes.
These are built into Java 7, but are also available as a separate download for Java 6.
![Page 3: 1 Apr 5, 2012 ForkJoin New in Java 7. Incrementor I package helloWorld; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.RecursiveTask;](https://reader036.vdocuments.mx/reader036/viewer/2022082820/56649e7b5503460f94b7d4fc/html5/thumbnails/3.jpg)
Incrementor II package helloWorld;
import java.util.concurrent.ForkJoinPool;import java.util.concurrent.RecursiveTask;
class Incrementor extends RecursiveTask<Integer> {
}
3
Next you need to create a class that extends RecursiveTask.
A RecursiveTask is like a Thread, but you can retrieve a value from it after it finishes. Supply a type parameter (Integer, in this example) to specify the kind of value you want.
![Page 4: 1 Apr 5, 2012 ForkJoin New in Java 7. Incrementor I package helloWorld; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.RecursiveTask;](https://reader036.vdocuments.mx/reader036/viewer/2022082820/56649e7b5503460f94b7d4fc/html5/thumbnails/4.jpg)
Incrementor III package helloWorld;
import java.util.concurrent.ForkJoinPool;import java.util.concurrent.RecursiveTask;
class Incrementor extends RecursiveTask<Integer> { public static ForkJoinPool fjPool = new ForkJoinPool();
}
4
Create a ForkJoinPool. Create only one of these, and it should be static.
A ForkJoinPool is a pool of Threads. Java will take care of all the thread allocation and deallocation for you.
![Page 5: 1 Apr 5, 2012 ForkJoin New in Java 7. Incrementor I package helloWorld; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.RecursiveTask;](https://reader036.vdocuments.mx/reader036/viewer/2022082820/56649e7b5503460f94b7d4fc/html5/thumbnails/5.jpg)
Incrementor IV package helloWorld;
import java.util.concurrent.ForkJoinPool;import java.util.concurrent.RecursiveTask;
class Incrementor extends RecursiveTask<Integer> { public static ForkJoinPool fjPool = new ForkJoinPool(); int theNumber; Incrementor(int x) { theNumber = x; } public Integer compute() { return theNumber + 1; } public static void main(String[] args) { int fortyThree = fjPool.invoke(new Incrementor(42)); Systemout.println(fortyThree); }}
5
Make an instance of our Incrementor class. We defined it to have a “generic” type parameter <Integer>, so let's define a field “theNumber” to hold it.
In this example, our constructor sets theNumber to have an initial value.
![Page 6: 1 Apr 5, 2012 ForkJoin New in Java 7. Incrementor I package helloWorld; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.RecursiveTask;](https://reader036.vdocuments.mx/reader036/viewer/2022082820/56649e7b5503460f94b7d4fc/html5/thumbnails/6.jpg)
Incrementor V package helloWorld;
import java.util.concurrent.ForkJoinPool;import java.util.concurrent.RecursiveTask;
class Incrementor extends RecursiveTask<Integer> { public static ForkJoinPool fjPool = new ForkJoinPool(); int theNumber; Incrementor(int x) { theNumber = x; } public Integer compute() { return theNumber + 1; } public static void main(String[] args) { int fortyThree = fjPool.invoke(new Incrementor(42)); System.out.println(fortyThree); }}
6
Define a compute() method.compute() is what we use in place of run().
![Page 7: 1 Apr 5, 2012 ForkJoin New in Java 7. Incrementor I package helloWorld; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.RecursiveTask;](https://reader036.vdocuments.mx/reader036/viewer/2022082820/56649e7b5503460f94b7d4fc/html5/thumbnails/7.jpg)
Incrementor VI package helloWorld;
import java.util.concurrent.ForkJoinPool;import java.util.concurrent.RecursiveTask;
class Incrementor extends RecursiveTask<Integer> { public static ForkJoinPool fjPool = new ForkJoinPool(); int theNumber; Incrementor(int x) { theNumber = x; } public Integer compute() { return theNumber + 1; } public static void main(String[] args) { int fortyThree = fjPool.invoke(new Incrementor(42)); System.out.println(fortyThree); }}
7
Finally, create a new Incrementor (like getting a Thread, but with a parameter), and tell the ForkJoinPool to invoke it (like calling its “start” method).
Calling “invoke” will cause “run” to be executed.
![Page 8: 1 Apr 5, 2012 ForkJoin New in Java 7. Incrementor I package helloWorld; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.RecursiveTask;](https://reader036.vdocuments.mx/reader036/viewer/2022082820/56649e7b5503460f94b7d4fc/html5/thumbnails/8.jpg)
What did that code do? int fortyThree = fjPool.invoke(new
Incrementor(42));
How is this any different from int fortyThree = new Incrementor(42).compute();?
Answer: compute runs as a RecursiveTask(because class Incrementor extends RecursiveTask<Integer>)
So what? RecursiveTasks are “lightweight” Threads (you can have up to 32767 of them)
which can fork and join public final ForkJoinTask<V> fork() arranges to asynchronously execute this
task. Any given task should only be forked once. public final V join(), unlike the Thread join, returns a result.
![Page 9: 1 Apr 5, 2012 ForkJoin New in Java 7. Incrementor I package helloWorld; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.RecursiveTask;](https://reader036.vdocuments.mx/reader036/viewer/2022082820/56649e7b5503460f94b7d4fc/html5/thumbnails/9.jpg)
Summing an array I: Contextimport java.util.concurrent.ForkJoinPool;import java.util.concurrent.RecursiveTask;
class Globals { static ForkJoinPool fjPool = new ForkJoinPool();}
class Sum extends RecursiveTask<Long> { protected Long compute() {…}
static long sumArray(int[] array) {…}}
9
We only ever need or want one ForkJoinPool:
Let’s make a RecursiveTask/compute() combination:
![Page 10: 1 Apr 5, 2012 ForkJoin New in Java 7. Incrementor I package helloWorld; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.RecursiveTask;](https://reader036.vdocuments.mx/reader036/viewer/2022082820/56649e7b5503460f94b7d4fc/html5/thumbnails/10.jpg)
Summing an array II: Parametersclass Sum extends RecursiveTask<Long> { static final int SEQUENTIAL_THRESHOLD = 5000;
int low; int high; int[] array;
Sum(int[] arr, int lo, int hi) { array = arr; low = lo; high = hi; } protected Long compute() {…}
static long sumArray(int[] array) {…}
} 10
We need to pass parameters in to compute().
But compute() doesn’t take parameters! What do we do?
Notice the constructor !
![Page 11: 1 Apr 5, 2012 ForkJoin New in Java 7. Incrementor I package helloWorld; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.RecursiveTask;](https://reader036.vdocuments.mx/reader036/viewer/2022082820/56649e7b5503460f94b7d4fc/html5/thumbnails/11.jpg)
Summing an array III: Doing the workclass Sum extends RecursiveTask<Long> {
protected Long compute() { if(high - low <= SEQUENTIAL_THRESHOLD) { long sum = 0; for(int i=low; i < high; ++i) sum += array[i]; return sum; } else { int mid = low + (high - low) / 2; Sum left = new Sum(array, low, mid); Sum right = new Sum(array, mid, high); left.fork(); long rightAns = right.compute(); long leftAns = left.join(); return leftAns + rightAns; } }}
11
Not much to do? Do it here.
Split the array into two parts.
Start another thread to sum the left half. I ’ll do the right half myself.
When I’m done, wait for the other thread.
![Page 12: 1 Apr 5, 2012 ForkJoin New in Java 7. Incrementor I package helloWorld; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.RecursiveTask;](https://reader036.vdocuments.mx/reader036/viewer/2022082820/56649e7b5503460f94b7d4fc/html5/thumbnails/12.jpg)
12
Let’s see that again
• We create two new Sums, one to fork and one to use ourself• Sum left = new Sum(array, low, mid);Sum right = new Sum(array, mid, high);
• We fork to sum the left half of the array• left.fork();
• We sum the right half ourselves, with a plain old method call (not anadditional Thread) that returns a result
• long rightAns = right.compute();
• When we are done, the fork may or may not be done.We wait for it. When it is done, we get its result
• long leftAns = left.join();
• Then, of course, we add the two results• return leftAns + rightAns; 12
![Page 13: 1 Apr 5, 2012 ForkJoin New in Java 7. Incrementor I package helloWorld; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.RecursiveTask;](https://reader036.vdocuments.mx/reader036/viewer/2022082820/56649e7b5503460f94b7d4fc/html5/thumbnails/13.jpg)
Summing an array IV: Begin here• class Sum extends RecursiveTask<Long> {
// other methods that we have been looking at
static long sumArray(int[] array) { return Globals.fjPool.invoke(newSum(array,0,array.length)); } }
The call to fjPool.invoke creates an instance of this Sum class, which is a RecursiveTask, and that gets the ball rolling.
invoke should not be called from within a RecursiveTask or RecursiveAction.It should only be called from sequential code.
15
![Page 14: 1 Apr 5, 2012 ForkJoin New in Java 7. Incrementor I package helloWorld; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.RecursiveTask;](https://reader036.vdocuments.mx/reader036/viewer/2022082820/56649e7b5503460f94b7d4fc/html5/thumbnails/14.jpg)
14
Running the exampleimport java.util.Random;
public class SumTester {
static Random rand = new Random();
public static void main(String[] args) {
int[] array = new int[100000];
for (int i = 0; i < array.length; i += 1) {
array[i] = rand.nextInt(11);
}
long sum = Sum.sumArray(array);
System.out.println(sum);
}
}
![Page 15: 1 Apr 5, 2012 ForkJoin New in Java 7. Incrementor I package helloWorld; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.RecursiveTask;](https://reader036.vdocuments.mx/reader036/viewer/2022082820/56649e7b5503460f94b7d4fc/html5/thumbnails/15.jpg)
15
The End