JAVA, got wrong value when using LongAdder in multi-thread - java

I am doing this exercise:
Generate 1,000 threads, each of which increments a counter
100,000 times. Compare the performance of using AtomicLong
versus LongAdder.
And the following is my implementation:
import java.io.*;
import java.util.*;
import java.nio.file.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
public class AtomicLongVsLongAddr {
// 9. Generate 1,000 threads, each of which increments a counter
// 100,000 times. Compare the performance of using AtomicLong
// versus LongAdder.
AtomicLong al = new AtomicLong(0);
LongAdder la = new LongAdder();
public class AtomicLongThread extends Thread {
#Override
public void run() {
for (int i = 0; i < 100000; i ++) {
al.incrementAndGet();
}
}
}
public class LongAdderThread extends Thread {
#Override
public void run() {
for (int i = 0; i < 100000; i ++) {
la.increment();
}
}
}
public static void main(String[] args) {
AtomicLongVsLongAddr vs = new AtomicLongVsLongAddr();
long startTime = System.currentTimeMillis();
for (int i = 0; i < 1000; i ++) {
(vs.new AtomicLongThread()).start();
}
long endTime = System.currentTimeMillis();
System.out.printf("AtomicLong--Number: %s, Time: %d\n", vs.al, endTime - startTime);
startTime = System.currentTimeMillis();
for (int i = 0; i < 1000; i ++) {
(vs.new LongAdderThread()).start();
}
long res = vs.la.sum();
endTime = System.currentTimeMillis();
System.out.printf("LongAdder--Number: %s, Time: %d\n", res, endTime - startTime);
}
}
I got something like the following as the standard output every time I run this program:
AtomicLong--Number: 100000000, Time: 2330
LongAdder--Number: 99882179, Time: 469
Apparently I've got a wrong value with LongAdder, but I can not figure out where I did wrong.
Can you help me?
updated
Under the help of everybody here and #Ravindra Ranwala, I updated my answer for the exercise above:
import java.io.*;
import java.util.*;
import java.nio.file.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
public class AtomicLongVsLongAddr {
// 9. Generate 1,000 threads, each of which increments a counter
// 100,000 times. Compare the performance of using AtomicLong
// versus LongAdder.
AtomicLong al = new AtomicLong(0);
LongAdder la = new LongAdder();
public class AtomicLongThread extends Thread {
#Override
public void run() {
for (int i = 0; i < 100000; i ++) {
al.incrementAndGet();
}
}
}
public class LongAdderThread extends Thread {
#Override
public void run() {
for (int i = 0; i < 100000; i ++) {
la.increment();
}
}
}
public static void main(String[] args) {
try{
long startTime;
long endTime;
AtomicLongVsLongAddr vs = new AtomicLongVsLongAddr();
Thread[] t = new Thread[1000];
for (int i = 0; i < 1000; i ++) {
t[i] = vs.new AtomicLongThread();
}
startTime = System.currentTimeMillis();
for (int i = 0; i < 1000; i ++) {
t[i].start();
t[i].join();
}
endTime = System.currentTimeMillis();
System.out.printf("AtomicLong--Number: %s, Time: %d\n", vs.al, endTime - startTime);
for (int i = 0; i < 1000; i ++) {
t[i] = vs.new LongAdderThread();
}
startTime = System.currentTimeMillis();
for (int i = 0; i < 1000; i ++) {
t[i].start();
t[i].join();
}
long res = vs.la.sum();
endTime = System.currentTimeMillis();
System.out.printf("LongAdder--Number: %s, Time: %d\n", res, endTime - startTime);
} catch (Exception e) {
e.printStackTrace();
}
}
}
If there still are any wrong, please point it out for me. Thanks everyone.

Call Thread.join on all the threads and wait till all of them are completed. It seems your main thread exits before other threads that increment the two variables completed. What you are getting here is some intermediary result.
Here's the code,
public static void main(String[] args) throws InterruptedException {
final List<Thread> adderThreads = new ArrayList<>();
final List<Thread> atomicThreads = new ArrayList<>();
AtomicLongVsLongAddr vs = new AtomicLongVsLongAddr();
long startTime = System.currentTimeMillis();
for (int i = 0; i < 1000; i++) {
final AtomicLongThread atomicThread = vs.new AtomicLongThread();
atomicThreads.add(atomicThread);
atomicThread.start();
}
for (Thread thread : atomicThreads) {
thread.join();
}
long endTime = System.currentTimeMillis();
System.out.printf("AtomicLong--Number: %s, Time: %d\n", vs.al, endTime - startTime);
startTime = System.currentTimeMillis();
for (int i = 0; i < 1000; i++) {
final LongAdderThread adderThread = vs.new LongAdderThread();
adderThreads.add(adderThread);
adderThread.start();
}
for (Thread thread : adderThreads) {
thread.join();
}
long res = vs.la.sum();
endTime = System.currentTimeMillis();
System.out.printf("LongAdder--Number: %s, Time: %d\n", res, endTime - startTime);
}

Your code isn't synchronous - The main thread will exit/proceed before it's finished with the counter threads, thus creating the difference.

Related

Inline Thread objects runs much faster than class that inherits from Thread

Here is a main that runs a simple counting loop three ways:
Single-threaded
2 threads using inline code that creates two distinct Thread objects
2 threads using instances of the CountingThread class that inherits from Thread
package main;
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
demo();
}
public static void demo() {
final long limit = 100_000_000_000L;
long startTime = System.currenatTimeMillis();
for (long i = 0; i < limit; i++) {
// Nothing to see here, just counting
}
long endTime = System.currentTimeMillis();
System.out.println("Single threaded: Total execution time: " + (endTime - startTime) + " milliseconds.");
// Now try it in two threads. Each thread will perform 1/2 of the counting
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
for (long i = 0; i < limit/2; i++) {
// Nothing to see here, just counting
}
}
});
Thread t2 = new Thread(new Runnable() {
#Override
public void run() {
for (long i = limit/2; i < limit; i++) {
// Nothing to see here, just counting
}
}
});
startTime = System.currentTimeMillis();
t1.start();
t2.start();
// Join t1 until it ends, then join t2 until it ends. Note that t1 and t2 are running in parallel with this thread.
try {t1.join();} catch (InterruptedException e) {}
try {t2.join();} catch (InterruptedException e) {}
endTime = System.currentTimeMillis();
System.out.println("2 threaded using inline code: Total execution time: " + (endTime - startTime) + " milliseconds.");
// Now try it with 2 instances of the CountingThread class.
ArrayList<CountingThread> countingThreads = new ArrayList<CountingThread>();
int numberOfThreads = 2;
long increment = limit / numberOfThreads;
for (int i = 0; i < numberOfThreads; i++) {
long start, end;
start = i * increment;
end = start + increment;
countingThreads.add(new CountingThread(start, end));
}
// Launch all the threads to run in parallel
startTime = System.currentTimeMillis();
for (int i = 0; i < numberOfThreads; i++) {
countingThreads.get(i).run();
}
// Wait for all the threads to finish
for (int i = 0; i < numberOfThreads; i++) {
try {countingThreads.get(i).join();} catch(InterruptedException ex) {}
}
endTime = System.currentTimeMillis();
System.out.println(numberOfThreads + " threaded using classes: Total execution time: " + (endTime - startTime) + " milliseconds.");
}
}
Here is the class that inherits from Thread:
package main;
/**
* Count from one long int up to another long int. Really simple
*
*/
public class CountingThread extends Thread {
private long start, end;
public CountingThread(long start, long end) {
this.start = start;
this.end = end;
}
#Override
public void run() {
for(long i = start; i <= end; i++) {
}
// System.out.println("Thread counted from " + start + " to " + end);
}
}
Here is the output:
Single threaded: Total execution time: 40379 milliseconds.
2 threaded using inline code: Total execution time: 23312 milliseconds.
2 threaded using classes: Total execution time: 40358 milliseconds.
It seems like methods 2 and 3 should take about the same amount of time. What's up with that?
The machine has 4 cores.
You made a mistake and call #run instead of #start. Run method is executed in the same thread.
countingThreads.get(i).run();

Stepping over from Concurrency to Parallel processing

I have a quad core cpu, and I've been trying to experiment with multithreading for performance reasons. I've written this code below just to see how fast it would go, and I noticed that it's actually slower than the 2nd code block that only uses the main thread
int numCrunchers = Runtime.getRuntime().availableProcessors();
public void crunch() {
int numPairs = 1000;
for(int i=0; i < numPairs; i++)
pairs.add(...);
int share = pairs.size()/numCrunchers;
for(int i=0; i < numCrunchers; i++) {
Cruncher cruncher = crunchers.get(i);
for(int j=0; j < share; j++)
cruncher.nodes.add(pairs.poll());
}
for(Cruncher cruncher : crunchers)
threadpool.execute(cruncher);
threadpool.shutdown();
try {
threadpool.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private class Cruncher implements Runnable {
public BlockingQueue<Pair<PathNode>> nodes = new LinkedBlockingQueue<Pair<PathNode>>();
private AStarPathfinder pathfinder;
private LinkedList<PathNode> path = new LinkedList<PathNode>();
public Cruncher(GridGraph graph) {
pathfinder = new AStarPathfinder(graph);
}
#Override
public void run() {
while(true) {
path.clear();
Pair<PathNode> pair = nodes.poll();
if(pair != null) {
pathfinder.search(path, pair.first(), pair.second());
paths.add(new LinkedList<PathNode>(path));
} else {
System.out.println("This cruncher is done");
break;
}
}
}
}
Each thread took around 34,000,000,000 nanoseconds on my pc, but when I decided to use no threads except for the main thread, it only took 1,090,195,046 nanoseconds, 34x time difference.
LinkedList<Pair<PathNode>> pairs = new LinkedList<Pair<PathNode>>();
int numPairs = 1000;
AStarPathfinder pathfinder = new AStarPathfinder(graph);
for(int i=0; i < numPairs; i++)
pairs.add(...);
long current = System.nanoTime();
for(int i=0; i < numPairs; i++) {
Pair<PathNode> pair = pairs.poll();
path.clear();
pathfinder.search(path, pair.first(), pair.second());
}
System.out.printf("Operation took %d nanoseconds", System.nanoTime() - current);
My question is why using multiple threads causes my program to run slow? Is the code not properly taking advantage of all the cores on my cpu? I ran this several times, and the results were similar, (30+)x time difference between multithreading and single-threading
Edit:
Decided to measure the time of each individual operation on the multithreaded
while(true) {
path.clear();
Pair<PathNode> pair = nodes.poll();
if(pair != null) {
long current = System.nanoTime();
pathfinder.search(path, pair.first(), pair.second());
paths.add(new LinkedList<PathNode>(path));
System.out.printf("Took %d nanoseconds\n", System.nanoTime() - current);
} else {
System.out.println("This cruncher is done");
break;
}
}
and single threaded...
LinkedList<Pair<PathNode>> pairs = new LinkedList<Pair<PathNode>>();
int numPairs = 1000;
AStarPathfinder pathfinder = new AStarPathfinder(graph);
for(int i=0; i < numPairs; i++)
pairs.add(...);
for(int i=0; i < numPairs; i++) {
long current = System.nanoTime();
Pair<PathNode> pair = pairs.poll();
path.clear();
pathfinder.search(path, pair.first(), pair.second());
System.out.printf("Operation took %d nanoseconds", System.nanoTime() - current);
}
Each Cruncher has its own AStarPathfinder instance, so the pathfinder.search() couldn't be causing blocking between each of the threads. The multithreaded application was still much slower.

How to measures the speed of a context switch on a UNIX/Linux system using Java program

I need to measure thread context switching I write below program is that correct way please let me know and wanted to get update on this post.
Any one can help.
/**
Below is the program which I am trying is this a correct way.
*/
public class JavaContextSwitch {
final static Object ob = new Object();
final static int numberOFThread=10;
final static MyThread []threadArray =new MyThread[numberOFThread];
public static void main(String args[]) throws InterruptedException{
long mainThreadStart=System.nanoTime();
for(int i=0;i<numberOFThread;i++){
threadArray[i]= new JavaContextSwitch.MyThread(numberOFThread);
threadArray[i].setPriority(Thread.MAX_PRIORITY);
threadArray[i].start();
threadArray[i].join();
}
System.out.println("All Thread is relaase for job and witing ..");
//Thread.currentThread().join();
System.out.println("Waiting is over ");
long endOfMainThread= System.nanoTime();
System.out.println("Total time taken is "+(endOfMainThread-mainThreadStart));
long sum=0;
for(int i=0;i<numberOFThread;i++){
long timeTaken= threadArray[i].timefinish-threadArray[i].startTime;
System.out.println("Each thread running time "+timeTaken);
sum=sum+timeTaken;
}
System.out.println("Total time taken by thread is "+sum);
System.out.println("Average "+numberOFThread+" Taken "+(sum/numberOFThread)+" Time ");
long timeForContextSwitch= (endOfMainThread-mainThreadStart)-sum;
System.out.println(" Context switch time is "+timeForContextSwitch);
System.out.println(" Average Context witching "+ (timeForContextSwitch/numberOFThread+1));
}
private static class MyThread extends Thread {
public long startTime;
public long timefinish;
int cycle = 0;
public MyThread(int cycle) {
this.cycle = cycle;
}
public void run() {
System.out.println(" Child thread started"+this.getId());
startTime=System.nanoTime();
// Child thread is busy to complete their job.
for (int i = 0; i < cycle; i++) {
for (int j = 0; j < 640 * 81; j++)
timefinish = System.nanoTime();
}
System.out.println("I am done now "+this.getId());
}
}
}

Need Help intrepretting the results of this program

So, I made a small program to test Multithreading in java and compare the time it takes to scale an array using a while loop and then creating multiple threads and running those threads. I'm unsure about then numbers I'm getting when the program finishes, so I was wondering if I made a boneheaded error at some point and messed something up to get very disparate numbers.
Code below:
import java.util.Scanner;
public class arrayScaling {
public static void main(String[] args) throws InterruptedException {
Scanner input = new Scanner(System.in);
System.out.println("Enter the amount of number you want the program to generate:");
int numOfNumbs = input.nextInt();
int [] arrayForNumbers = new int [numOfNumbs];
int [] newArrayForNumbers = new int [numOfNumbs];
for (int i = 0; i < arrayForNumbers.length; i++) {
arrayForNumbers[i] = (int) ((Math.random() * 25) + 1);
}
long startTime = System.nanoTime();
for (int i = 0; i < arrayForNumbers.length; i++) {
newArrayForNumbers[i] = newArrayForNumbers[i] * 3;
}
long endTime = System.nanoTime();
System.out.println();
long totalExecutionTime = endTime-startTime;
System.out.println("Time it takes execute scaling is " +
totalExecutionTime + " nanoseconds");
System.out.println();
int numOfNumLeftOver = numOfNumbs % 5;
int numOfNumDivided = numOfNumbs / 5;
int [] temp = null;
int [] temp2 = null;
int [] temp3 = null;
int [] temp4 = null;
int [] temp5 = null;
MyThread thread1 = new MyThread (numOfNumbs/5);
MyThread thread2 = new MyThread (numOfNumbs/5);
MyThread thread3 = new MyThread (numOfNumbs/5);
MyThread thread4 = new MyThread (numOfNumbs/5);
MyThread thread5;
if (numOfNumLeftOver != 0) {
numOfNumDivided = numOfNumDivided + numOfNumLeftOver;
thread5 = new MyThread (numOfNumDivided);
}
else {
thread5 = new MyThread (numOfNumbs/5);
}
int tempNum = 0;
for ( int i = 0; i < thread1.getArray().length; i ++) {
temp = thread1.getArray();
temp[tempNum] = arrayForNumbers[tempNum];
tempNum++;
}
for ( int i = 0; i < thread2.getArray().length; i ++) {
temp2 = thread2.getArray();
temp2[i] = arrayForNumbers[tempNum];
tempNum++;
}
for ( int i = 0; i < thread3.getArray().length; i ++) {
temp3 = thread3.getArray();
temp3[i] = arrayForNumbers[tempNum];
tempNum++;
}
for ( int i = 0; i < thread4.getArray().length; i ++) {
temp4 = thread4.getArray();
temp4[i] = arrayForNumbers[tempNum];
tempNum++;
}
for ( int i = 0; i < thread5.getArray().length; i ++) {
temp5 = thread5.getArray();
temp5[i] = arrayForNumbers[tempNum];
tempNum++;
}
thread1.setArray(temp);
thread2.setArray(temp2);
thread3.setArray(temp3);
thread4.setArray(temp4);
thread5.setArray(temp5);
long startTime2 = System.nanoTime();
thread1.start();
thread2.start();
thread3.start();
thread4.start();
thread5.start();
thread1.join();
thread2.join();
thread3.join();
thread4.join();
thread5.join();
long endTime2 = System.nanoTime();
long newTotalExecutionTime = endTime2 - startTime2;
System.out.println("Time it takes execute scaling w/ multiple threads is " +
newTotalExecutionTime + " nanoseconds");
if (newTotalExecutionTime < totalExecutionTime) {
System.out.println("Multithreading was more effective");
}
else if (totalExecutionTime < newTotalExecutionTime) {
System.out.println("The original algorithm was more effective");
}
else if (totalExecutionTime == newTotalExecutionTime) {
System.out.println("Both method worked at the same speed");
}
input.close();
}
}
public class MyThread extends Thread {
private int [] array;
private int [] scaleArray;
public MyThread(int size) {
array = new int [size];
scaleArray = new int [size];
}
public int[] getArray() {
return array;
}
public void setArray(int[] array) {
this.array = array;
}
public int[] getScaleArray() {
return scaleArray;
}
public void setScaleArray(int[] scaleArray) {
this.scaleArray = scaleArray;
}
public void run () {
for (int z = 0; z < array.length; z++){
scaleArray[z] = 3 * array[z];
}
}
}
And the output of this program is:
Enter the amount of number you want the program to generate:
16
Time it takes execute scaling is 893 nanoseconds
Time it takes execute scaling w/ multiple threads is 590345 nanoseconds
The original algorithm was more effective
Your results don't surprise me in the slightest. There's a lot of overhead to creating threads, starting them, waiting for them to finish and so on. Don't forget, 590345ns is still less than a millisecond; but most of that is to do with shuffling threads, not with multiplying the numbers.
If you want to see the threaded part of the program outperform the other part, try generating a whole lot more than 16 numbers.

Infinite for loop

This code works fine:
public class Main {
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
long endTime = startTime + 60000;
long index = 0;
while (true) {
double x = Math.sqrt(index);
long now = System.currentTimeMillis();
if (now > endTime) {
break;
}
index++;
}
System.out.println(index + " loops in one minute.");
}
}
But then, I tried rewriting it into a for loop, and it gets stuck in an infinite loop.
public class Main {
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
long endTime = startTime + 60000;
int i = 0;
for (long now = 0; now < endTime; i++) {
Math.sqrt(i);
now = System.currentTimeMillis();
System.out.println("now" + now);
System.out.println("end" + endTime);
}
}
System.out.println(i+"calculations done in one minute");
}
Your second example is not an infinite loop, just wait 1 minute.
long endTime = startTime + 60000;
set the endTime to 60000 milliseconds in the future, that means 60 seconds, means 1 minute.
The standard output is just printing extremely fast.
Put a Thread.sleep(1000L) in the loop and you will see 61 statements being printed before it ends.
long endTime = 1378140843604L; // for example
for (long now = 0; now < endTime; i++) {
now = System.currentTimeMillis(); // will be 1378140783604, 1378140784604, 1378140785604 and so on
System.out.println("now" + now);
System.out.println("end" + endTime);
Thread.sleep(1000L);
}
This worked for me:
public class Main {
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
long endTime = startTime + 60000;
int i = 0;
for (long now = 0; now < endTime; i++) {
Math.sqrt(i);
now = System.currentTimeMillis();
System.out.println("now" + now);
System.out.println("end" + endTime);
}
System.out.println(i+"calculations done in one minute");
}
}
The only difference between mine an yours is where I put this: (yours is outside the main method)
System.out.println(i+"calculations done in one minute");
You should also be aware it take just microseconds to run through the loop so you're getting a huge output.

Categories