I was trying to do some analysis on calling start and join simultaneously,
//Starting and Joining
for (Thread thread : threadArray) {
thread.start();
thread.join();
}
compared with start first and then join.
//Starting Them
for (Thread thread : threadArray) {
thread.start();
}
//Joining Them
for (Thread thread : threadArray) {
thread.join();
}
What would be the performance difference between the above two cases?.
In the first scenario, I am pretty much guaranteeing that the order of execution is sequential between threads. So if I have n threads and say each thread takes Ti time to complete the task, my total time of execution should be sum of Tis from 1 to n.
In the second scenario, I am starting off and then joining. This is the part which I am getting confused. Shouldn’t the time be almost same as above?. What I am seeing is almost double on my machine.
The entire code sample I am using is given below.
public class ThreadJoin implements Runnable {
public void run() {
for (int i=0;i<10000000;i++) {
//Random mathematical stuff independent of i.
int ran = (int) (Math.random()*1000 -34)%47;
}
}
public static void main(String[] args) throws Exception {
Thread[] threadArray = new Thread[10];
//Creating threads and feeding them with the job
for (int i=0;i<10;i++) {
threadArray[i] = new Thread(new ThreadJoin());
}
long currentTimeMillis = System.currentTimeMillis();
System.out.println("Started at " + currentTimeMillis);
//Starting Them
for (Thread thread : threadArray) {
thread.start();
}
//Joining Them
for (Thread thread : threadArray) {
thread.join();
}
long currentTimeMillis2 = System.currentTimeMillis();
System.out.println("Ended at " + currentTimeMillis2);
System.out.println("Diff : " +( currentTimeMillis2 - currentTimeMillis));
}
}
In theory, starting first all the threads and then joining them all should allow your 10 threads to execute concurrently (i.e. at the same time), while starting and joining the threads in one loop will make them run in parallel.
So, in theory, the two-loop variant should be faster. Why is it actually slower (if I understand this right)?
You are using
Math.random()in your loop quite heavily. In fact, I suppose most of the work occurs in this method.Math.random() is a synchronized method – this means that only one thread at a time can execute it, and the other ones have to wait until the previous one is finished.
So, you can’t really get faster than sequentially here. It actually gets slower since you have lots of context switches between your many threads, most of which will then find out they can’t continue since another thread already has the lock.
To make your program faster, let each thread have its own
java.util.Random()object, and call itsnextRandom()method instead. (You might want to make sure that they are initialized with different seeds, though.)As mentioned in the comment from Tomek, from Java 7 on there is the
ThreadLocalRandomclass, which organizes such a pool of Random objects per thread and exposes the one for the current thread by itscurrent()method. (I did never use this, so I can’t comment on the performance compared to doing this manually.)