Reputation: 19612
I am working on a Multithreading Program in which I am trying to make sure each Thread is running for 30 minutes
. Suppose if we have 10 threads
then each thread out of 10
should run for 30 minutes
.
Below is my code-
class ThreadTask implements Runnable {
private final long endTime;
public ThreadTask(long endTime) {
this.endTime = endTime;
}
@Override
public void run() {
while (System.currentTimeMillis() <= endTime) {
// do something meaningful
}
}
}
public class TestPool {
public static void main(String[] args) {
// create thread pool with given size
ExecutorService service = Executors.newFixedThreadPool(1000);
long startTime = System.currentTimeMillis();
long endTime = startTime + (30 * 60 * 1000);
for (int i = 0; i < threads; i++) {
service.submit(new ThreadTask(endTime));
}
// wait for termination
service.shutdown();
service.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
}
}
Now my question is-
Does the above code guarantee that each thread is starting at the same time and running for 30 minutes
? I am not sure how much time it takes to put the thread in Thread Pool. But it looks like it might be possible that some of the thread will start little bit late and they won't be running for exactly 30 minutes
, might be less than 30 minutes.
I am looking for each thread should start at same time and they should run for exactly
30 minutes
Upvotes: 5
Views: 7837
Reputation: 3730
Consider using countdown latch to achieve maximum parallelism. Basically you can create singleton/static countdownLatch with total count 1 and let multiple threads waited up for same countdown. check below what I've done
The main thread that dictates the thread starting time.
package mylab.threads;
import java.util.TimerTask;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class MainThread extends TimerTask {
private static CountDownLatch countDown = new CountDownLatch(1);
private ExecutorService es = Executors.newCachedThreadPool();
@Override
public void run() {
try {
Thread1 thread1 = new Thread1();
thread1.setDoneSignal(countDown);
es.submit(thread1);
Thread2 thread2 = new Thread2();
thread2.setDoneSignal(countDown);
es.submit(thread2);
System.out.println("waiting main.. ");
synchronized(this) {
this.wait(2000);
}
System.out.println("kick off threads..");
countDown.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Define threads you want to run parallel
package mylab.threads;
import java.util.Date;
import java.util.TimerTask;
import java.util.concurrent.CountDownLatch;
public class Thread1 extends TimerTask{
private CountDownLatch doneSignal = null;
/**
* @return the doneSignal
*/
public CountDownLatch getDoneSignal() {
return doneSignal;
}
/**
* @param doneSignal the doneSignal to set
*/
public void setDoneSignal(CountDownLatch doneSignal) {
this.doneSignal = doneSignal;
}
@Override
public void run() {
try {
this.doneSignal.await();
System.out.println("get going thread 1 -"+new Date().getTime());
synchronized(this) {
this.wait(3000);
}
System.out.println("Exiting thread 1 - "+new Date().getTime());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
package mylab.threads;
import java.util.Date;
import java.util.TimerTask;
import java.util.concurrent.CountDownLatch;
public class Thread2 extends TimerTask{
private CountDownLatch doneSignal = null;
/**
* @return the doneSignal
*/
public CountDownLatch getDoneSignal() {
return doneSignal;
}
/**
* @param doneSignal the doneSignal to set
*/
public void setDoneSignal(CountDownLatch doneSignal) {
this.doneSignal = doneSignal;
}
@Override
public void run() {
try {
this.doneSignal.await();
System.out.println("get going thread 2 -"+new Date().getTime());
synchronized(this) {
this.wait(3000);
}
System.out.println("Exiting thread 2 - "+new Date().getTime());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Finally run main thread.
package mylab.threads;
public class ThreadTest {
/**
* @param args
*/
public static void main(String[] args) {
MainThread mt = new MainThread();
mt.run();
}
}
Here is the output
waiting main..
kick off threads..
get going thread 1 -1387513662107
get going thread 2 -1387513662107
Exiting thread 1 - 1387513665108
Exiting thread 2 - 1387513665108
Upvotes: 0
Reputation: 3895
Short answer: No, all the threads will not start exactly at the same time (depending on what your tolerance is, it could be 'quite' negligible). And depending on what something meaningful does, there is very little chance that each thread runs exactly 30 minutes (again here, your time granularity could make this assertion wrong).
Leads:
EDIT:
public class TestPool {
public static void main(String[] args) {
// create thread pool with given size
ExecutorService service = Executors.newFixedThreadPool(10);
long startTime = System.currentTimeMillis();
long endTime = startTime + (30 * 60 * 1000);
ThreadTask[] threadTasks = new ThreadTask[threads];
for (int i = 0; i < threads; i++) {
threadTasks[i] = new ThreadTask(endTime);
}
for (ThreadTask tt : threadTasks) {
service.submit(tt);
}
// wait for termination
service.shutdown();
service.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
}
}
Upvotes: 1
Reputation: 1474
At first glance, this looks like a somewhat unrealistic multithreading excercise project. But you say I am working on a Multithreading Program which suggests there is a real-world application background to it.
If that's the case: Do not create 1000 threads just because you can. Instead, say what you actually want to achieve.
About your requirements: To start all the threads almost at the same time with minimum delay, you can prestartAllCoreThreads
of a ThreadPoolExecutor
. Submit Runnables that have // do something meaningful
in their run Method. To limit the run time to 30 minutes, schedule a TimerTask that after 30min shuts down the ThreadPoolExecutor with shutdownNow. When creating the ThreadPoolExecutor, you can use a fixed-size BlockingQueue with a size in the order of your desired thread count to avoid submitting too many jobs.
Upvotes: 0