recursive task that does its work not completely - java

I have tried to create a recursive task that divides a set of elements into smaller pieces and runs a series of math works on them, say numerically integration, then tries to use separate results for each element. but it seems that an error occurs before the pool does its works completely. my code tries to reach the elements that are not yet processed.
could you please help me with this?
public void ComputeStiffnessMatrix(DataScanner DS){
ans=new double [2*(DS.getXarray().length)][2*(DS.getXarray().length)];
int nelels=((DS.getNelKsi())*(DS.getNelEta()));
ArrayList<ElementStiffness> elsm=new ArrayList<>();
StiffnessMatrix SM=new StiffnessMatrix(elsm,DS,0,(nelels-1));
ForkJoinPool pool = new ForkJoinPool();
System.out.println("Stiffness Matrix Computation...");
long startTime = System.currentTimeMillis();
pool.invoke(SM);
long endTime = System.currentTimeMillis();
System.out.println("Stiffness Matrix Computation took " + (endTime - startTime) + " milliseconds.");
System.out.println("Arranging into an array...");
long startTime2 = System.currentTimeMillis();
try {
ArrayList<ElementStiffness> kk=(ArrayList<ElementStiffness>) SM.get();
for (int el=0;el<nelels;el++){
ElementStiffness pp=kk.get(el);
System.out.println("EL NO."+el);
double vals[][]=pp.getStiffnessMatrix();
int sup[]=pp.getControlpointsSupport();
for (int i=0;i<sup.length;i++){
for (int j=0;j<sup.length;j++){
ans[(2*sup[i])+0][(2*sup[j])+0]=ans[(2*sup[i])+0][(2*sup[j])+0]+vals[(2*i)+0][(2*j)+0];
ans[(2*sup[i])+0][(2*sup[j])+1]=ans[(2*sup[i])+0][(2*sup[j])+1]+vals[(2*i)+0][(2*j)+1];
ans[(2*sup[i])+1][(2*sup[j])+0]=ans[(2*sup[i])+1][(2*sup[j])+0]+vals[(2*i)+1][(2*j)+0];
ans[(2*sup[i])+1][(2*sup[j])+1]=ans[(2*sup[i])+1][(2*sup[j])+1]+vals[(2*i)+1][(2*j)+1];
}
}
}
} catch (InterruptedException | ExecutionException ex) {
Logger.getLogger(IGATest.class.getName()).log(Level.SEVERE, null, ex);
}
long endTime2 = System.currentTimeMillis();
System.out.println("Stiffness Matrix rearrangement took " + (endTime2 - startTime2) + " milliseconds.");
try{
FileOutputStream fs=new FileOutputStream("stifmat.tmp");
ObjectOutputStream os=new ObjectOutputStream(fs);
os.writeObject(ans);
os.close();
}catch (IOException e){
e.printStackTrace();
}
ans=null;
}
And the siffnessmatrix class:
public class StiffnessMatrix extends RecursiveTask {
private final int min;
private final int max;
private final DataScanner ds;
ArrayList<ElementStiffness> elsm;
public StiffnessMatrix (ArrayList<ElementStiffness> elsm,DataScanner DS,int min, int max){
this.ds=DS;
this.min=min;
this.max=max;
this.elsm=elsm;
}
protected void compdir(){
for (int i=min;i<=max;i++){
double[] elsp=ds.getElementSpan(i);
Element el=new Element(ds,((elsp[0]+elsp[1])*0.5),((elsp[2]+elsp[3])*0.5));
ElementStiffness els=new ElementStiffness(ds,el);
elsm.add(els);
}
}
#Override
protected ArrayList <ElementStiffness> compute(){
int processors = Runtime.getRuntime().availableProcessors();
if (max-min<processors) {
compdir();
} else {
int center = min + (max - min) / 2;
invokeAll(new StiffnessMatrix(elsm,ds, min, center) , new StiffnessMatrix(elsm, ds, center+1, max));
}
return elsm;
}
}

Related

Fastest way to search in milliseconds

I have to find what is the fastest way to search the max random number from my array within a range
So I create one method that search normal "using one thread" and another one that use threads
I have Class:MaxThread
import java.util.stream.IntStream;
public class MaxThread extends Thread {
private final int from;
private final int to;
public MaxThread(int[] tab, int from, int to) {
this.from = from;
this.to = to;
}
#Override
public void run() {
long start = System.currentTimeMillis();
int max = IntStream.of(from, to)
.max()
.getAsInt();
long end = System.currentTimeMillis() - start;
System.out.println("Max number from threads is : " + max);
System.out.println("Founded in: " + end + " [ms] ");
}
}
Class: Main2
public class Main2{
public static void main(String[] args) {
int[] tab = new int[200000000];
for (int i = 0; i < tab.length; i++) {
tab[i] = random(0, 200000000);
}
int max = searchMax(0, 50000000);
System.out.println("Max number without using threads " + max);
MaxThread maxThread = new MaxThread(tab, 25000000, 150000000);
maxThread.start();
}
public static int random(int start, int end) {
Random rnd = new Random();
return rnd.nextInt(end - start + 1) + start;
}
public static int searchMax(int from, int to) {
long start = System.currentTimeMillis();
int max = IntStream.of(from, to)
.parallel()
.max()
.getAsInt();
long end = System.currentTimeMillis() - start;
System.out.println("Founded in: " + end + " [ms] ");
return max;
}
}
I count the time in ms inside the method but I want to see witch one was the fastest to find the number , but here is where I cannot find out the way to do it.
Can someone give me and hint please?

Print the rank of runner according to finishing their thread

I have a Runner class which extends Thread. In main class, I have bunch of objects of Runner class which start race at the same time. I want to print the rank of each runner based on the time taken to finish their thread.
private void raceStart() throws InterruptedException
{
long start = System.currentTimeMillis();
Thread.sleep((long) (reaction * 1000));
int track = 100;
int playerLocation = 0;
Random randomDelay = new Random();
double delay = 90 + randomDelay.nextInt(16);
for(int i = 0; i <= track; i++)
{
if(playerLocation == track)
{
long finish = System.currentTimeMillis();
double totalTime = (double)(finish - start) / 1000;
System.out.format("%d %d %d %-12s %-12s %-25s %.3f %.3f%n" , rank, lane, bib, country, lastName, firstName, reaction, totalTime);
}
playerLocation++;
Thread.sleep((long) delay);
}
}
In my main class,
private void run()
{
Runner usainBolt = new Runner(1, 6, 2612, "JAM", "Bolt", "Usain", 0.155);
Runner justinGatlin = new Runner(2, 4, 3069, "USA", "GATLIN", "Justin", 0.152);
Runner andreDeGrasse = new Runner(3, 7, 2196, "CAN", "DE GRASSE", "Andre", 0.141);
Runner yohanBlake = new Runner(4, 9, 2611, "JAM", "BLAKE", "Yohan", 0.145);
Runner akaniSimbine = new Runner(5, 3, 2909, "RSA", "SIMBINE", "Akani", 0.128);
Runner benYoussefMeite = new Runner(6, 8, 2245, "CIV", "MEITE", "Ben Youssef", 0.156);
Runner jimmyVicaut = new Runner(7, 5, 2434, "FRA", "VICAUT", "Jimmy", 0.140);
Runner trayvonBromell = new Runner(8, 2, 3054, "USA", "BROMWELL", "Trayvon", 0.135);
List<Runner> runners = Arrays.asList(usainBolt, justinGatlin, andreDeGrasse,
yohanBlake, akaniSimbine, benYoussefMeite, jimmyVicaut, trayvonBromell);
for (Runner r : runners)
{
r.start();
}
I also want to print the total time taken by the whole program in the end.
I tried
long start = System.currentTimeMillis();
run(0);
long finish = System.currentTimeMillis();
double totalTime = (double)(finish - start) / 1000;
System.out.println("totalTime");
But it always prints 0 or 1 before displaying the results.
Since a lot of this is time recording based, I'd recommend creating a simple StopWatch class that each runner can hold on to and record their individual times.
public class StopWatch {
private long startTime = -1;
private long stopTime = -1;
private long currentTime = 0;
private boolean isRunning = false;
public void start(){
isRunning = true;
startTime = System.nanoTime();
}
public void stop(){
stopTime = System.nanoTime();
}
public long getCurrentTime(){
if (startTime != -1 && stopTime == -1){
currentTime = System.nanoTime() - startTime;
}else if (startTime != -1 && stopTime != -1){
currentTime = stopTime - startTime;
}
return currentTime;
}
public boolean isRunning(){
if(startTime != -1 && stopTime == -1){
isRunning = true;
}
return isRunning;
}
public void reset(){
startTime = -1;
stopTime = -1;
currentTime = 0;
isRunning = false;
}
}
I'm not sure what your Runner class looks like but I've made just a simple one that determines speed randomly and adds a random amount every second to each runner(you can create your own method in Runner to determine how quick each runner is). I would also implement comparable to runner so that you can sort them based on distance traveled and finally overide toString() method in Runner to print the relevant information that will be used for the leaderboard later.
import java.util.Random;
import java.util.concurrent.TimeUnit;
public class Runner extends Thread implements Comparable {
boolean hasFinished = false;
int distanceTraveled = 0;
StopWatch timer = new StopWatch();
Random speed = new Random();
int raceDistanceMeters = 100;
private String nameF;
private String nameL;
public Runner(String nameL, String nameF) {
this.nameF = nameF;
this.nameL = nameL;
}
public void run() {
timer.start();
while(hasFinished == false){
try {
Thread.sleep(1000);
distanceTraveled = distanceTraveled + speed.nextInt(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (distanceTraveled >= raceDistanceMeters){
hasFinished = true;
distanceTraveled = raceDistanceMeters;
timer.stop();
}
}
}
#Override
public int compareTo(Object compareRunner) {
int compareDistanceTraveled = ((Runner)compareRunner).distanceTraveled;
return compareDistanceTraveled-this.distanceTraveled;
}
#Override
public String toString() {
return this.nameF + " " + this.nameL + " " + "Distance: " + distanceTraveled + " Time: " + (Double.valueOf(TimeUnit.NANOSECONDS.toMillis(timer.getCurrentTime())))/1000;
}
}
You can now use ArrayLists of type Runner with Collections.sort and also print each of the runners after sorting.
A Race class makes sense as it will allow some house keeping items related to that specific race such as the runners competing along with printing a leaderboard.
public class Race {
ArrayList<Runner> runners = new ArrayList<>();
public void addRunner(Runner runner){
runners.add(runner);
}
public void start(){
runners.forEach(runner -> runner.start());
}
public void printLeaderboard(){
Collections.sort(runners);
System.out.println();
System.out.println();
System.out.println();
System.out.println();
System.out.println("-------------------------------------------------------------");
runners.forEach(runner -> System.out.println(runner.toString()));
}
public boolean isRaceOver() {
int count = 0;
for (Runner runner : runners) {
if (runner.hasFinished == true){
count++;
}
}
if (count == runners.size()){
return true;
}
return false;
}
}
So an example of what Main() would look like.
public class Main {
public static void main(String[] args) throws InterruptedException {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ArrayList<Runner> runners = new ArrayList<>();
runners.add(new Runner("Bolt", "Usain"));
runners.add(new Runner("GATLIN", "Justin"));
runners.add(new Runner("DE GRASSE", "Andre"));
runners.add(new Runner("BLAKE", "Yohan"));
runners.add(new Runner("SIMBINE", "Akani"));
runners.add(new Runner("MEITE", "Ben Youssef"));
runners.add(new Runner("VICAUT", "Jimmy"));
runners.add(new Runner("BROMWELL", "Trayvon"));
Race race1 = new Race();
runners.forEach(runner -> race1.addRunner(runner));
race1.start();
while (!race1.isRaceOver()){
Thread.sleep(500);
race1.printLeaderboard();
}
System.out.println("Total Run time: " + (Double.valueOf(TimeUnit.NANOSECONDS.toMillis(stopWatch.getCurrentTime())))/1000);
}
}

Stopwatch Class

public class Stopwatch {
private double startTime;
private double endTime;
public static void main(String[]args) {
}
public void stopWatch() {
startTime = System.currentTimeMillis();
}
public void start() {
startTime = System.currentTimeMillis();
}
public void stop() {
endTime = System.currentTimeMillis();
}
public long getStartTime()
{
return (long) startTime;
}
public long getEndTime()
{
return (long) endTime;
}
public long getElapsedTime()
{
return (long) (System.currentTimeMillis() - startTime);
}
public short getMilliSeconds()
{
return (short)((System.currentTimeMillis() - startTime) % 1000);
}
}
I need to run this testSearch with the StopWatch Class above
When I input the array size I get the Linear Search result but the Binary Search stays at 0 nano seconds
import java.util.*;
public class testSearch {
public static void main(String[] args){
// input array size from user
Scanner input = new Scanner(System.in);
System.out.print("Enter array size: ");
int size = input.nextInt();
System.out.println();
// create the array (the numbers do not really matter)
int[] numbers = new int[size];
for(int i=0; i<numbers.length; i++){
// we want the numbers sorted for binary search
// so why not just the numbers 0,1,...,size-1
numbers[i]=i;
}
// store the time now
long startTime = System.nanoTime();
// linear search for size (which is not in the array)
linearSearch(numbers,size);
// display the time elapsed
System.out.println("The time taken by Linear Search is " + (System.nanoTime() - startTime) + "nanoseconds.");
// prepare to measure the time elapsed again
startTime = System.nanoTime();
// binary search for size
binarySearch(numbers,size);
// display the time elapsed
System.out.println("The time taken by Binary Search is " + (System.nanoTime() - startTime) + "nanoseconds.");
}
public static boolean linearSearch(int[] a, int key) {
for(int i=0; i<a.length; i++){
if(a[i]==key) return true;
}
return false;
}
public static boolean binarySearch(int[] a, int key) {
int low = 0;
int high = a.length -1;
int mid;
while (low <= high) {
mid = (low + high) / 2;
if (a[mid]>key) {
high = mid - 1;
} else if (a[mid]<key) {
low = mid + 1;
} else {
return true;
}
}
return false;
}
}
Here is the output that I get
Enter array size:
2
The time taken by Linear Search is 1456959922854 milliseconds.
The time taken by Binary Search is 0 milliseconds.

Producer Consumer-Average Wait times not outputting/buffer query

I am currently making a hypothetical producer consumer problem using java. The object is to have an operating system which is 1000 bytes, but only 500 bytes available to use for threads as 500 bytes have already been consumed by drivers and other operations. The threads are as follows:
A thread to start a BubbleWitch2 session of 10 seconds, which requires 100 bytes of RAM per
second
A thread to start a Spotify stream of 20 seconds, which requires 250 bytes of RAM per second
You should also take into account the fact that the operating system is simultaneously supporting system
activity and managing the processor, memory and disk space of the device on which it is installed.
Therefore, additionally create:
System and management threads, which, together, require 50 bytes of RAM per second, and
execute for a random length of time, once invoked.
A thread to install a new security update of 2 KB, which will be stored to disk, and requires 150
bytes of RAM per second while installing. Assume sufficient disk capacity in the system to support
this thread.
The operating system has only capacity for 200 bytes per second, therefore a larger thread such as spotify will experience delays or be forced to wait. I have used code which as far as I can tell, implements this. I am also required to generate exit times which I have done with timestamps and to calculate average waiting times for threads.
I have included code in my solution for the average waiting times with system.out.print but no matter what I do, it is not actually outputting the times at all-as if they did not exist.
I am also not sure if the buffer size limitations are working as it is a matter of milliseconds-is there any way to tell if this is working from the code below?
My main method.
public class ProducerConsumerTest {
public static void main(String[] args) throws InterruptedException {
Buffer c = new Buffer();
BubbleWitch2 p1 = new BubbleWitch2(c,1);
Processor c1 = new Processor(c, 1);
Spotify p2 = new Spotify(c, 2);
SystemManagement p3 = new SystemManagement(c, 3);
SecurityUpdate p4 = new SecurityUpdate(c, 4, p1, p2, p3);
p1.setName("BubbleWitch2 ");
p2.setName("Spotify ");
p3.setName("System Management ");
p4.setName("Security Update ");
p1.setPriority(10);
p2.setPriority(10);
p3.setPriority(10);
p4.setPriority(5);
c1.start();
p1.start();
p2.start();
p3.start();
p4.start();
p2.join();
p3.join();
p4.join();
System.exit(0);
}
}
My buffer class
import java.text.DateFormat;
import java.text.SimpleDateFormat;
/**
* Created by Rory on 10/08/2014.
*/
class Buffer {
private int contents, count = 0, process = 0;
private boolean available = false;
private long start, end, wait, request= 0;
private DateFormat time = new SimpleDateFormat("mm:ss:SSS");
public synchronized int get() {
while (process <= 500) {
try {
wait();
} catch (InterruptedException e) {
}
}
process -= 200;
System.out.println("CPU After Process " + process);
notifyAll();
return contents;
}
public synchronized void put(int value) {
while (process >= 1000) {
start = System.currentTimeMillis();
try {
wait();
} catch (InterruptedException e) {
}
end = System.currentTimeMillis();
wait = end - start;
count++;
request += wait;
System.out.println("Application Request Wait Time: " + time.format(wait));
process += value;
contents = value;
notifyAll();
}
}
}
My security update class
import java.lang.*;
import java.lang.System;
/**
* Created by Rory on 11/08/2014.
*/
class SecurityUpdate extends Thread {
private Buffer buffer;
private int number;
private int bytes = 150;
private int process = 0;
public SecurityUpdate(Buffer c, int number, BubbleWitch2 bubbleWitch2, Spotify spotify, SystemManagement systemManagement) throws InterruptedException {
buffer = c;
this.number = number;
bubbleWitch2.join();
spotify.join();
systemManagement.join();
}
public void run() {
for (int i = 0; i < 15; i++) {
buffer.put(i);
System.out.println(getName() + this.number
+ " put: " + i);
try {
sleep(1500);
} catch (InterruptedException e) {
}
}
System.out.println("-----------------------------");
System.out.println("Security Update has finished executing.");
System.out.println("------------------------------");
}
}
My processor class
class Processor extends Thread {
private Buffer processor;
private int number;
public Processor(Buffer c, int number) {
processor = c;
this.number = number;
}
public void run() {
int value = 0;
for (int i = 0; i < 60; i++) {
value = processor.get();
System.out.println("Processor #"
+ this.number
+ " got: " + value);
}
}
}
My bubblewitch class
import java.lang.*;
import java.lang.System;
import java.sql.Timestamp;
/**
* Created by Rory on 10/08/2014.
*/
class BubbleWitch2 extends Thread {
private Buffer buffer;
private int number;
private int bytes = 100;
private int duration;
public BubbleWitch2(Buffer c, int pduration) {
buffer = c;
duration = pduration;
}
long startTime = System.currentTimeMillis();
public void run() {
for (int i = 0; i < 10; i++) {
buffer.put(bytes);
System.out.println(getName() + this.number
+ " put: " + i);
try {
sleep(1000);
} catch (InterruptedException e) {
}
}
long endTime = System.currentTimeMillis();
long timeTaken = endTime - startTime;
java.util.Date date = new java.util.Date();
System.out.println("-----------------------------");
System.out.println("BubbleWitch2 has finished executing.");
System.out.println("Time taken to execute was " +timeTaken+ " milliseconds");
System.out.println("Time Bubblewitch2 thread exited Processor was " + new Timestamp(date.getTime()));
System.out.println("-----------------------------");
}
}
My system management
class SystemManagement extends Thread {
private Buffer buffer;
private int number, min = 1, max = 15;
private int loopCount = (int) (Math.random() * (max - min));
private int bytes = 50;
private int process = 0;
public SystemManagement(Buffer c, int number) {
buffer = c;
this.number = number;
}
public void run() {
for (int i = 0; i < loopCount; i++) {
buffer.put(50);
System.out.println(getName() + this.number
+ " put: " + i);
try {
sleep(1000);
} catch (InterruptedException e) {
}
}
System.out.println("-----------------------------");
System.out.println("System Management has finished executing.");
System.out.println("-----------------------------");
}
}
My spotify class
import java.sql.Timestamp;
/**
* Created by Rory on 11/08/2014.
*/
class Spotify extends Thread {
private Buffer buffer;
private int number;
private int bytes = 250;
public Spotify(Buffer c, int number) {
buffer = c;
this.number = number;
}
long startTime = System.currentTimeMillis();
public void run() {
for (int i = 0; i < 20; i++) {
buffer.put(bytes);
System.out.println(getName() + this.number
+ " put: " + i);
try {
sleep(1000);
} catch (InterruptedException e) {
}
}
long endTime = System.currentTimeMillis();
long timeTaken = endTime - startTime;
java.util.Date date = new java.util.Date();
System.out.println(new Timestamp(date.getTime()));
System.out.println("-----------------------------");
System.out.println("Spotify has finished executing.");
System.out.println("Time taken to execute was " + timeTaken + " milliseconds");
System.out.println("Time that Spotify thread exited Processor was " + date);
System.out.println("-----------------------------");
}
}
I may need to add timestamps to one or two classes yet but does anyone have any idea how to get my average times to actually print out? Or what is preventing it and if the buffer limitation is effectively being shown here(given that we are talking about milliseconds?)
Thanks.
The reason why sys out's are not printing is because of the below condition in your buffer class:-
public synchronized void put(int value) {
while (process >= 1000) {
.....
notifyAll();
}
}
this condition never gets satisified as the process never is greater than 1000
This is the reason why your Processor thread also gets stuck because when it calls get() it finds that the process is less than 500 and hence it indefinitely waits when it reaches the wait() line of code.
Rectifying the process condition appropriately in your put should let your missing sys out get printed
public synchronized void put(int value) {
if(process <= 500) {
process+=value;
} else {
//while (process >= 1000) {
start = System.currentTimeMillis();
try {
wait();
} catch (InterruptedException e) {
}
end = System.currentTimeMillis();
wait = end - start;
count++;
request += wait;
System.out.println("Application Request Wait Time: " + time.format(wait));
process += value;
contents = value;
//}
}
notifyAll();
}
If you want securityupdate thread to always run at the last then the correct way of using join within that thread is as below:-
class SecurityUpdate extends Thread {
private Buffer buffer;
private int number;
private int bytes = 150;
private int process = 0;
private BubbleWitch2 bubbleWitch2;
private Spotify spotify;
private SystemManagement systemManagement;
public SecurityUpdate(Buffer c, int number, BubbleWitch2 bubbleWitch2, Spotify spotify, SystemManagement systemManagement) throws InterruptedException {
buffer = c;
this.number = number;
this.bubbleWitch2 = bubbleWitch2;
this.spotify = spotify;
this.systemManagement = systemManagement;
}
public void run() {
try {
bubbleWitch2.join();
spotify.join();
systemManagement.join();
} catch (InterruptedException e) {
}
System.out.println("Finally starting the security update");
for (int i = 0; i < 15; i++) {
buffer.put(bytes); // Paul check if it should be i or bytes
System.out.println(getName() + this.number
+ " put: " + i);
try {
sleep(1500); // Paul why is this made to sleep 1500 seconds?
} catch (InterruptedException e) {
}
}
System.out.println("-----------------------------");
System.out.println("Security Update has finished executing.");
System.out.println("------------------------------");
}
}

ExecutorService.submit(<callable>) taking more time?

I am trying to understand the utilities in java.util.concurrent package and learnt that we can submit callable objects to the ExecutorService, which returns Future, which is filled with the value returned by the callable, after successful completion of task within call() method.
I am understanding that all the callables are executed concurrently using multiple threads.
When I wanted to see how much improvement ExecutorService gives over the batch task execution, i thought of capturing time.
Following is the code which i tried to execute -
package concurrency;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class ExecutorExample {
private static Callable<String> callable = new Callable<String>() {
#Override
public String call() throws Exception {
StringBuilder builder = new StringBuilder();
for(int i=0; i<5; i++) {
builder.append(i);
}
return builder.toString();
}
};
public static void main(String [] args) {
long start = System.currentTimeMillis();
ExecutorService service = Executors.newFixedThreadPool(5);
List<Future<String>> futures = new ArrayList<Future<String>>();
for(int i=0; i<5; i++) {
Future<String> value = service.submit(callable);
futures.add(value);
}
for(Future<String> f : futures) {
try {
System.out.println(f.isDone() + " " + f.get());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
long end = System.currentTimeMillis();
System.out.println("Executer callable time - " + (end - start));
service.shutdown();
start = System.currentTimeMillis();
for(int i=0; i<5; i++) {
StringBuilder builder = new StringBuilder();
for(int j=0; j<5; j++) {
builder.append(j);
}
System.out.println(builder.toString());
}
end = System.currentTimeMillis();
System.out.println("Normal time - " + (end - start));
}
}
and here is the output of this -
true 01234
true 01234
true 01234
true 01234
true 01234
Executer callable time - 5
01234
01234
01234
01234
01234
Normal time - 0
Please let me know if I am missing something OR understanding something in a wrong way.
Thanks in advance for your time and help for this thread.
If you task in Callable is to small, you won't get benefits from concurrency due task switching and overhead for initialisation. Try to add more heavier loop in callable, say 1000000 iterations, and you can see difference
When you run any code esp for the first time, it takes time. If you pass a task to another thread it can take 1-10 micro-seconds and if your task take less time than this, the overhead can be greater than the benefit. i.e. using multiple threads can be much slower than using a single thread if your overhead is high enough.
I suggest you
increase the cost of the task to 1000 iterations.
make sure the result is not discarded in the single threaded example
run both tests for at least a couple of seconds to ensure the code has warmed up.
Not an answer (but I am not sure the code will fit a comment). To expand a bit on what Peter said, there is usually a sweet spot for the size of your jobs (measured in execution time), to balance pool/queue overhead with fair work distribution among workers. The code example helps find an estimate for that sweet spot. Run on your target hardware.
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
public class FibonacciFork extends RecursiveTask<Long> {
private static final long serialVersionUID = 1L;
public FibonacciFork( long n) {
super();
this.n = n;
}
static ForkJoinPool fjp = new ForkJoinPool( Runtime.getRuntime().availableProcessors());
static long fibonacci0( long n) {
if ( n < 2) {
return n;
}
return fibonacci0( n - 1) + fibonacci0( n - 2);
}
static int rekLimit = 8;
private static long stealCount;
long n;
private long forkCount;
private static AtomicLong forks = new AtomicLong( 0);
public static void main( String[] args) {
int n = 45;
long times[] = getSingleThreadNanos( n);
System.out.println( "Single Thread Times complete");
for ( int r = 2; r <= n; r++) {
runWithRecursionLimit( r, n, times[ r]);
}
}
private static long[] getSingleThreadNanos( int n) {
final long times[] = new long[ n + 1];
ExecutorService es = Executors.newFixedThreadPool( Math.max( 1, Runtime.getRuntime().availableProcessors() / 2));
for ( int i = 2; i <= n; i++) {
final int arg = i;
Runnable runner = new Runnable() {
#Override
public void run() {
long start = System.nanoTime();
final int minRuntime = 1000000000;
long runUntil = start + minRuntime;
long result = fibonacci0( arg);
long end = System.nanoTime();
int ntimes = Math.max( 1, ( int) ( minRuntime / ( end - start)));
if ( ntimes > 1) {
start = System.nanoTime();
for ( int i = 0; i < ntimes; i++) {
result = fibonacci0( arg);
}
end = System.nanoTime();
}
times[ arg] = ( end - start) / ntimes;
}
};
es.execute( runner);
}
es.shutdown();
try {
es.awaitTermination( 1, TimeUnit.HOURS);
} catch ( InterruptedException e) {
System.out.println( "Single Timeout");
}
return times;
}
private static void runWithRecursionLimit( int r, int arg, long singleThreadNanos) {
rekLimit = r;
long start = System.currentTimeMillis();
long result = fibonacci( arg);
long end = System.currentTimeMillis();
// Steals zählen
long currentSteals = fjp.getStealCount();
long newSteals = currentSteals - stealCount;
stealCount = currentSteals;
long forksCount = forks.getAndSet( 0);
System.out.println( "Fib(" + arg + ")=" + result + " in " + ( end-start) + "ms, recursion limit: " + r +
" at " + ( singleThreadNanos / 1e6) + "ms, steals: " + newSteals + " forks " + forksCount);
}
static long fibonacci( final long arg) {
FibonacciFork task = new FibonacciFork( arg);
long result = fjp.invoke( task);
forks.set( task.forkCount);
return result;
}
#Override
protected Long compute() {
if ( n <= rekLimit) {
return fibonacci0( n);
}
FibonacciFork ff1 = new FibonacciFork( n-1);
FibonacciFork ff2 = new FibonacciFork( n-2);
ff1.fork();
long r2 = ff2.compute();
long r1 = ff1.join();
forkCount = ff2.forkCount + ff1.forkCount + 1;
return r1 + r2;
}
}

Categories