Reputation: 424
I am starting multiple threads(around 1000) from my code. They are Runnable threads called from a while loop. How do I calculate the total time taken for all threads to finish executing?
Also I am opening a DB Connection and have a set of queries for which I am starting these threads(1 thread for 1 query). When do I close the connection?
Upvotes: 5
Views: 15933
Reputation: 5344
In general you cannot measure time execution exactly because context switching. If you have 1000 threads it is produce significant impact to all time measuring. Nevertheless if you may omit high exactness of time measuring you may use CountDownLautching primitive to synchronizing thread starting and thread finishing:
public static void main( String[] args ) throws InterruptedException {
final int THREAD_COUNT = 10000;
long startTime;
long endTime;
final CountDownLatch startBarierr = new CountDownLatch(THREAD_COUNT + 1);
final CountDownLatch finishBarierr = new CountDownLatch(THREAD_COUNT);
for (int i = 0; i < THREAD_COUNT; i++){
final int iterationIndex = i;
new Thread(new Runnable() {
@Override
public void run() {
startBarierr.countDown();
System.out.println("Thread " + iterationIndex + " started");
try {
startBarierr.await();
//do some work in separate thread
int iterationCount = (int)(0.8*Integer.MAX_VALUE);
for(int i = 0; i < iterationCount; i++){
}
System.out.println("Thread " + iterationIndex + " finished");
finishBarierr.countDown(); //current thread finished, send mark
} catch (InterruptedException e) {
throw new AssertionError("Unexpected thread interrupting");
}
}
}).start();
}
startBarierr.countDown();
startBarierr.await(); //await start for all thread
startTime = System.currentTimeMillis(); //and note time
finishBarierr.await(); //wait each thread
endTime = System.currentTimeMillis(); //note finish time
System.out.println("Time(ms) - " + (endTime - startTime));
}
Upvotes: 1
Reputation: 120848
You need another Thread to wait until these 1000 Threads have finished their work, you can do that with a CountDownLatch, but you need to know the exact number of Threads that you have - 1000 in your case.
Something like this:
public class LatchTest {
public static void main(String[] args) throws Exception {
final CountDownLatch latch = new CountDownLatch(100);
long startTime = System.nanoTime();
for(int i=0;i<100;++i){
new Thread(new Runnable() {
public void run() {
//Simulate some work
latch.countDown();
}).start();
}
// Main Thread will wait for all Threads to finish
latch.await();
long finishTime = System.nanoTime();
System.out.println("Have passed : " + (finishTime - startTime));
}
}
Upvotes: 1
Reputation: 1685
Use a CountDownLatch like mentioned here.
public class StopLatchedThread extends Thread {
private final CountDownLatch stopLatch;
public StopLatchedThread(CountDownLatch stopLatch) {
this.stopLatch = stopLatch;
}
public void run() {
try {
// perform interesting task
} finally {
stopLatch.countDown();
}
}
}
public void performParallelTask() throws InterruptedException {
CountDownLatch cdl = new CountDownLatch(10);
for (int i = 0; i < 10; i++) {
Thread t = new StopLatchedThread(cdl);
t.start();
}
cdl.await();
}
Upvotes: 3
Reputation: 272257
Why not throw them all into an Executor, and call get() on each resultant Future in turn?
Once the last thread completes, then you'll have called your last get() and you can time that complete operation.
Upvotes: 1
Reputation: 533500
I would use an ExecutorService
long start = System.nanoTime();
ExecutorService service = Executors.newWhatEverPool();
for(loop)
service.submit(new MyRunnable());
service.shutdown();
service.awaitTermination(1, TimeUnit.HOUR); // or longer.
long time = System.nanoTime() - start;
System.out.printf("Tasks took %.3f ms to run%n", time/1e6);
Close the connection when you have finished with it. It is a common pattern for the creator of a resource to also close it. e.g. If the main thread creates the connection, it could close after all the threads have finished.
Upvotes: 8
Reputation: 890
Probably the easiest way is to put those Threads on a list and checking in intervals whether any of them is alive (Thread.isAlive() method), taking the dead ones off the list. Repeat until list is empty. Downside is that it'll give you the time with some error margin.
The other solution is to inject 'parent' controller into those threads, then make them report back upon finishing. The same logic applies - we can pull a finished thread from list (or some other kind of set) until our list is empty. This method is more precise, but requires adding additional logic into threads.
Upvotes: 0