I am looking to learn about using the Java CountDownLatch to control the execution of a thread.
I have two classes. One is called Poller and the other is Referendum. The threads are created in the Referendum class and their run() methods are contained in the Poller class.
In the Poller and Referendum classes I have imported the java countdown latch via import java.util.concurrent.CountDownLatch.
I am mainly looking to understand why and where the the *.countDown(); and *.await(); statements need to be applied and also to understand if I have correctly initialised the countDownLatch within the Poller constructor.
The complete code for the two classes are:
import java.util.concurrent.CountDownLatch;
public class Poller extends Thread
{
private String id; // pollster id
private int pollSize; // number of samples
private int numberOfPolls; // number of times to perform a poll
private Referendum referendum; // the referendum (implies voting population)
private int sampledVotes[]; // the counts of votes for or against
static CountDownLatch pollsAreComplete; //the CountDownLatch
/**
* Constructor for polling organisation.
* #param r A referendum on which the poller is gathering stats
* #param id The name of this polling organisation
* #param pollSize The size of the poll this poller will use
* #param pollTimes The number of times this poller will conduct a poll
* #param aLatch The coutn down latch that prevents the referendum results from being published
*/
public Poller(Referendum r, String id, int pollSize, int pollTimes, CountDownLatch aLatch)
{
this.referendum = r;
this.id = id;
this.pollSize = pollSize;
this.numberOfPolls = pollTimes;
this.pollsAreComplete = aLatch;
aLatch = new CountDownLatch(3);
// for and against votes to be counted
sampledVotes = new int[2];
}
// getter for numberOfPolls
public int getNumberOfPolls()
{
return numberOfPolls;
}
#Override
//to use the countdown latch
public void run()
{
for (int i = 0; i < getNumberOfPolls(); i++)
{
resetVotes();
pollVotes();
publishPollResults();
}
}
// make sure all sampledVotes are reset to zero
protected void resetVotes()
{
// initialise the vote counts in the poll
for (int i = 0; i < sampledVotes.length; i++)
{
sampledVotes[i] = 0;
}
}
// sampling the way citizens will vote in a referendum
protected void pollVotes()
{
for (int n = 0; n < pollSize; n++)
{
Citizen c = referendum.pickRandomCitizen();
//As things stand, pickRandomCitizen can return null
//because we haven't protected access to the collection
if (c != null)
{
sampledVotes[c.voteFor()]++;
}
}
}
protected void publishPollResults()
{
int vfor = 100 * sampledVotes[Referendum.FOR] / pollSize;
int vagainst = 100 * sampledVotes[Referendum.AGAINST] / pollSize;
System.out.printf("According to %-20s \t(", this.id + ":");
System.out.print("FOR " + vfor);
try
{
Thread.sleep(1000);
} catch (Exception e)
{
e.printStackTrace();
}
System.out.println(", AGAINST " + vagainst + ")");
}
}
And
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
public class Referendum
{
private List<Citizen> citizens; //voters
private List<Poller> pollers; //vote samplers
public static final int FOR = 0; //index for votes array
public static final int AGAINST = 1; //index for votes array
private int votes[]; //for and against votes counters
public Referendum(int population)
{
citizens = new LinkedList<Citizen>();
pollers = new LinkedList<Poller>();
// initialise the referendum with the population
for (int i = 0; i < population; i++)
{
Citizen c = new Citizen(i % 4); //suppose equal party membership
citizens.add(c);
}
votes = new int[2]; //in this example, only For or Against
}
public void addPoller(Poller np)
{
pollers.add(np);
}
public Citizen removeCitizen(int i)
{
return citizens.remove(i);
}
public List<Poller> getPollers()
{
return pollers;
}
public void startPollsWithLatch()
{
//create some poller threads that use a latch
addPoller(new Poller(this, "The Daily Day", 100, 3, Poller.pollsAreComplete));
addPoller(new Poller(this, "Stats people", 100, 3, Poller.pollsAreComplete));
addPoller(new Poller(this, "TV Pundits", 100, 3, Poller.pollsAreComplete));
// start the polls
for (Poller p : pollers)
{
p.start();
}
}
// pick a citizen randomly - access not controlled yet
public Citizen pickRandomCitizen()
{
//TODO add code to this method for part (b)
Citizen randomCitizen;
// first get a random index
int index = (int) (Math.random() * getPopulationSize());
randomCitizen = citizens.remove(index);
return randomCitizen;
}
// Counting the actual votes cast in the referendum
public void castVotes()
{
for (int h = 0; h < getPopulationSize(); h++)
{
Citizen c = citizens.get(h);
votes[c.voteFor()]++;
}
}
// tell the size of population
public int getPopulationSize()
{
return citizens.size();
}
// display the referendum results
public void revealResults()
{
System.out.println(" **** The Referendum Results are out! ****");
System.out.println("FOR");
System.out.printf("\t %.2f %%\n", 100.0 * votes[FOR] / getPopulationSize());
System.out.println("AGAINST");
System.out.printf("\t %.2f %%\n", 100.0 * votes[AGAINST] / getPopulationSize());
}
public static void main(String[] args)
{
// Initialise referendum. The number of people
// has been made smaller here to reduce the simulation time.
Referendum r = new Referendum(50000);
r.startPollsWithLatch();
r.castVotes();
// reveal the results of referendum
r.revealResults();
}
}
In a nutshell...
All threads must execute the publishPollResults(); statement BEFORE the revealResults(); is executed.
OK,
Now, if the publishPollResults must be done by all before the reavelResults, then simply you need to wait for the proper count in your reaveal method. But to do so, the latch must be also shared with the referendum object not only with Pollers.
so, let the referendum creates the latch and pass it to the pollers:
public class Referendum
{
CountDownLatch pollsAreComplete;
...
public void startPollsWithLatch()
{
pollsAreComplete = new CountDownLatch(3); //create new latch to know when the voting is done
//create some poller threads that use a latch
addPoller(new Poller(this, "The Daily Day", 100, 3, pollsAreComplete)); //pass it to pollers
addPoller(new Poller(this, "Stats people", 100, 3, pollsAreComplete));
addPoller(new Poller(this, "TV Pundits", 100, 3, pollsAreComplete));
// start the polls
for (Poller p : pollers)
{
p.start();
}
}
public void revealResults()
{
pollsAreComplete.await(); //we can pass this line only if the latch count went to 0
System.out.println(" **** The Referendum Results are out! ****");
....
}
}
so the Pollers should share the latch. You are using static variable which is OKish but you want be able to use the Pollers with different referendums.
So it is betther, that have it is a instance field and pass it in constructor (you kind of started with constructor but then you passed the value to static variable which makes no sense (and it actaully was always null).
public class Poller extends Thread
{
...
private CountDownLatch pollsAreComplete; //the CountDownLatch shared with referendum
public Poller(Referendum r, String id, int pollSize, int pollTimes, CountDownLatch aLatch)
{
...
this.pollsAreComplete = aLatch;
}
public void run()
{
for (int i = 0; i < getNumberOfPolls(); i++)
{
resetVotes();
pollVotes();
publishPollResults();
}
pollsAreComplete.countDown(); //voting is finished, let the referendum publish the results.
}
}
So once the Poller finished its work it lowers the latch, and when all do it the referendum can continue and print the results.
Mind you all Poller thread will publish their results 3 times (as they have for loop) and only when all 3 are cycles are down they will signal the referendum.
If you wanted the 3 separate phases of referendum it will be very difficult to achieve if with latch as it cannot be reset once it's been down to 0.
If I understood correctly, you want all threads to execute before the results are shown. This requires a single CountDownLatch instance in the Referendum class that is passed to the constructor of each Poller thread. Each Pollercalls countdown() on the latch once it ends the poll, and Referendum calls await() to sleep until the latch countdown reaches zero:
class Referendum {
private CountDownLatch latch;
public CountDownLatch getLatch() {
return latch;
}
// ...
public void startVotesWithLatch() {
// You don't need to pass the latch in constructor,
// as you can retrieve it from the referendum object passed
addPoller(new Poller(this, "Stats people", 100, 3));
// Add other pollers
// Start all pollers
for (Poller p : pollers) {
p.start();
}
// Wait for all pollers to finish
latch.await();
}
}
And in the Poller class remove the latch variable as it is not needed, then in the publishPollResults() method:
public void publishPollResults() {
// Everything stays the same here, except we decrease the latch
// when finished...
referendum.getLatch().countDown();
}
Note however that this type of synchronization is quite simple and does not necessarily require a CountDownLatch, you can simply spawn your Poller threads and then call join() on the main thread (this will pause the main thread until the child threads finish execution).
Related
I'm currently working on a problem where I have to:
Write out a letter, x amount of times, after x amount of ms. Use 4 multithreads, 3 of them start right away 1 of them starts when one of the 3 is finished.
For example: A, 10, 100, has to write out A ever 10 times every 100 miliseconds.
Im currently stuck on syncing the multithreads for them to work together at adding one sum rather than them working seporatley. Could you advise how to sync it together for it to write out the above?
Here is my code:
public class PrinterThread extends Thread {
private String letter;
private int internal;
private int amount;
public PrinterThread() {
for (int i = 1; i <= internal; i++) {
System.out.println(letter);
}
synchronized (this){
internal++;
}
try {
Thread.sleep(amount);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class Main {
public static void main(String[] args) {
PrinterThread printerThread = new PrinterThread();
PrinterThread printerThread1 = new PrinterThread();
PrinterThread printerThread2 = new PrinterThread();
PrinterThread printerThread3 = new PrinterThread();
printerThread.run();
printerThread1.run();
printerThread2.run();
printerThread3.run();
}
}
Use a BlockingQueue for synchronisation, but you do need to join with the threads from your main method otherwise your main will exit the JVM before the threads finish (or possibly even before they start).
public class PrinterThread implements Runnable {
private String letter;
private int copies;
private int amount;
public PrinterThread(String letter, int copies, int amount) {
this.letter = letter;
this.copies = copies;
this.amount = amount;
}
public void run() {
for (int i = 0; i < copies; i++) {
System.out.println(letter.repeat(copies));
try {
Thread.sleep(amount);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
QUEUE.offer(0);
}
}
public class Main {
private static BlockingQueue<Integer> QUEUE = new ArrayBlockingQueue<>(4); // at least as large as the number of threads
public static void main(String[] args) {
Thread printerThread1 = new Thread(new PrinterThread("A", 10, 100));
Thread printerThread2 = new Thread(new PrinterThread("B", 20, 50));
// etc
printerThread1.start();
printerThread2.start();
// etc
QUEUE.take(); // blocking call
new Thread(new PrinterThread("D", 30, 80)).start();
// wait for threads to finish
printerThread1.join();
printerThread2.join();
// etc
}
}
Disclaimer: This answer was thumbed in via my phone, so it may not work correctly or even compile, but there’s a good chance it will work.
Write out a letter, x amount of times, after x amount of ms. Use 4 multithreads, 3 of them start right away 1 of them starts when one of the 3 is finished.
You obviously need to create a PrinterThread constructor which takes the letter, the amount of times, and amount of millis.
I'm currently stuck on syncing the multithreads for them to work together at adding one sum rather than them working separately.
I'm not sure about the sum. If you are asking how you can start the 3rd thread then there are a number of different ways to do this. I would lock on a lock object and pass in a boolean in the constructor about whether or not the thread should wait() on the lock. As each of the other threads finish they would call notify() on the lock.
private static final Object lock = new Object();
...
public class PrinterThread {
public PrinterThread(char letter, int times, int millis, boolean waitForOthers) {
this.letter = letter;
this.times = times;
this.millis = millis;
if (waitForOthers) {
synchronized (lock) {
// wait for one of the others to notify us
lock.wait();
}
}
}
public void run() {
...
synchronized (lock) {
// notify the lock in case another thread is waiting
lock.notify();
}
}
Then start 3 PrinterThreads with a value of false and 1 of them with a value of true so that it waits.
I am new in concurrent threads in java. I am trying to code a simple horse race simulation.
I want to know which thread finished first.
This code below throws an error: incompatible types: Thread cannot be converted to Gate
winner = (Gate)Thread.currentThread();
Gate.java
public class Gate implements Runnable{
public String horseName;
public final int GATE_DISTANCE = 20;
public final int FINISH_LINE_DISTANCE = 100;
public CyclicBarrier barrier;
public Gate(CyclicBarrier barrier,String horseName){
this.horseName = horseName;
this.barrier = barrier;
}
public void run(){
//Walk all horses to respective racing gates before starting race
for(int distanceCovered = 0; distanceCovered < GATE_DISTANCE;){
distanceCovered += gallop();
int distanceLeft = GATE_DISTANCE - distanceCovered;
if(distanceLeft < 0){
distanceLeft = 0;
}
System.out.println(horseName + "\t\tgate distance left " + distanceLeft);
if(distanceLeft == 0){
break;
}
}
//Wait for all horses to be at racing gates
try{
barrier.await();
}
catch(InterruptedException ie){
System.out.println("INTERRUPTED");
}
catch(BrokenBarrierException bbe){
System.out.println("BROKEN");
}
//ACTUAL HORSE RACE
for(int distanceCovered = 0; distanceCovered < FINISH_LINE_DISTANCE;){
distanceCovered += gallop();
int distanceLeft = FINISH_LINE_DISTANCE - distanceCovered;
if(distanceLeft < 0){
distanceLeft = 0;
}
System.out.println(horseName + "\t\tgate distance left " + distanceLeft);
if(distanceLeft == 0){
break;
}
}
Main.done();
}
public int gallop(){
final int MIN_GALLOP = 1,
MAX_GALLOP = 10;
Random random = new Random();
int gallopRange = MAX_GALLOP - MIN_GALLOP + 1;
int totalGallop = random.nextInt(gallopRange) + MIN_GALLOP;
return totalGallop;
}
}
GateMain.java
public class GateMain{
private static Gate winner = null;
public static void main(String[] args) {
int horseCount = 5;
List<String> horseNames = new ArrayList<String>();
List<Thread> RG = new ArrayList<Thread>();
horseNames.add("Red Bullet");
horseNames.add("Green Furious");
horseNames.add("Pink Mirage");
horseNames.add("Blue Dash");
horseNames.add("Yellow Burst");
Scanner scan = new Scanner(System.in);
final CyclicBarrier cb = new CyclicBarrier(horseCount,new Runnable(){
public void run(){
System.out.print("\nALL HORSES ARE IN THEIR RESPECTIVE RACING GATES");
System.out.println("\nRACE BEGIN!!!\n");
}
});
for(int horseCtr = 0; horseCtr < horseCount; horseCtr++){
Gate rg = new Gate(cb,horseNames.get(horseCtr));
Thread thread = new Thread(rg);
thread.start();
RG.add(thread);
}
for(Thread thread: RG){
try{
thread.join();
}
catch(InterruptedException ie){
System.out.println("Thread Interrupted");
}
}
System.out.println(winner.horseName + "\t\t\twins!");
}
synchronized static void done(){
if(winner == null){
winner = (Gate)Thread.currentThread();
}
}
}
I would use a global AtomicInteger.
public static AtomicInteger finishLine = new AtomicInteger(0);
Each horse (thread) should have its own place variable,
int place;
and when a horse finishes the race, it sets its own place:
place = finishLine.incrementAndGet();
The first horse to reach the finish line will get place=1, the second horse, place=2, and so on. Then the main() routine must then examine each horse to find out which one has place=1. That'll be the winner.
Here's a different idea, inspired by the finish-line of a cross-country foot race: Instead of an AtomicInteger, use a thread-safe queue.
public static ArrayBlockingQueue<Horse> chute =
new ArrayBlockingQueue<>(NUMBER_OF_HORSES);
When each horse reaches the finish line, it enters the chute.
chute.add(this);
This way, there is no need to explicitly wait for the race to end, and there is no need to explicitly sort the finishers:
Horse win = chute.take(); //waits for the first horse to finish
Horse place = chute.take(); //waits for the second horse
Horse show = chute.take(); //...
However, just synchronizing here will not work, according to the rules of Java. You have to synchronize the update that you want the thread to read, as well. Depending on what variable is, that may or may not be a problem.
You may need to think out your threading model a bit more, and describe here what you want to do. If you were unaware of mutual exclusion, you may not be ready to design threaded code.
if you're trying to access an instance field from a static member, I have to wonder how you got the code to compile.
Thread.currentThread() returns the actual Thread object you (or some other library code) created. That can be a Gate thread, but it all depends on the Thread object it is running in. Safest is to use instanceof to check first.
According to docs Thread.currentThread() returns a reference to the current thread, not the object. So, you should look for reference to the object i.e this keyword.
You wish to have winner as a private member. You can't change it from run() in another class. So, you can pass the current object from run() as an argument to a method in GateMain by this.
You can edit the done() method as:
synchronized static void done(Gate new_gate){
if(winner == null){
winner = new_gate;
}
}
Replace the line Main.done() with Main.done(this)
I'm learning threads so I wanted to make a program which has two types of threads: one that writes random numbers and the other one which checks if the current number matches some specific number. The threads call write() and read(int) methods from the Numbers class. To make things more clear, I want my main program to look like this:
Numbers n = new Numbers();
new WritingThread(n);
new ReadingThread(n,3);
new ReadingThread(n,5);
So the output would be something like this:
2
7
3 !!! MATCH !!!
8
5 !!! MATCH !!!
1
...
The thing is that threads are not executed in order. I want to first execute the WritingThread, and then all the ReadingThreads. Because this way a new random number would be written and only one thread would have the chance to check if the numbers match. Here is the code:
class Numbers:
public class Numbers {
int number;
boolean written = false;
public synchronized void write() {
while (written)
try {
wait();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
number = (int) (Math.random() * 10);
System.out.print("\n" + number);
written = true;
notifyAll();
}
public synchronized void check(int n) {
while (!written)
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.print(" Reading thread: " + Thread.currentThread().getName());
if (n == number)
System.out.print(" !!! MATCH !!! ");
notify();
written = false;
}
}
class WritingThread:
public class WritingThread extends Thread {
Numbers n;
WritingThread(Numbers n){
this.n = n;
start();
}
public void run(){
while(true){
n.write();
}
}
}
class ReadingThread:
public class ReadingThread extends Thread{
Numbers n;
int number;
public ReadingThread(Numbers n, int number){
this.n = n;
this.number = number;
start();
}
public void run(){
while(true){
n.check(number);
}
}
}
And the output:
3 Reading thread: Thread-2
3 Reading thread: Thread-1 !!! MATCH !!!
0 Reading thread: Thread-2
5 Reading thread: Thread-1
0 Reading thread: Thread-2
0 Reading thread: Thread-1
5 Reading thread: Thread-2 !!! MATCH !!!
8 Reading thread: Thread-1
I know i could make one thread which has an array of numbers to check, but I am curious how could it be done this way. Thanks.
Lets start with your example. You have two consumers and one boolean flag. Think through the logic. Let's call our three threads W, C1 and C2.
W post 5
W set flag to true
W send notifyAll
C2 awake
C1 awake
C2 acquire lock
C1 block
C2 no match
C2 notify
W awake
W blocks
C2 release lock
C1 acquire lock
flag is false, C1 waits (releases monitor)
flag is false, C2 waits (releases monitor)
GOTO start
This is just one if the many possible ways in which this code can fun. Any time the lock needs to be acquired there is a free for all and of the threads waiting for it only one can get the lock. That thread will check the value set and reset the flag. If that thread is not the one that the value was intended for it is still consumed.
It should be fairly obvious that you have a race hazard. You are using a single queue for two consumer threads. Each consumer thread is fighting for the queue. Your queue is thread safe in that no more than one thread can read the single item from it at any one time but it causes a race hazard as each consumer thread expects to be the only one reading it. If the wrong thread reads the item then the other thread cannot see it.
The only way to resolve this is to have one queue per thread. The producer puts the same item into each consumer thread's private queue and each consumer thread takes items from its queue and reads them.
Here is an example using an ExecutorSerivce:
public static void main(String[] args) throws Exception {
final class Consumer implements Runnable {
private final BlockingQueue<Integer> q = new LinkedBlockingDeque<>();
private final int search;
public Consumer(final int search) {
this.search = search;
}
#Override
public void run() {
while (true) {
try {
if (q.take() == search) {
System.out.println("Found magic number.");
}
} catch (InterruptedException ex) {
return;
}
}
}
public Queue<Integer> getQ() {
return q;
}
}
final class Producer implements Runnable {
final Random r = new Random();
final Iterable<Queue<Integer>> qs;
public Producer(final Iterable<Queue<Integer>> qs) {
this.qs = qs;
}
#Override
public void run() {
while (true) {
final int i = r.nextInt();
for (final Queue<Integer> q : qs) {
q.offer(i);
}
}
}
}
final int numConsumers = 5;
final Collection<Queue<Integer>> qs = new LinkedList<>();
final ExecutorService es = Executors.newCachedThreadPool();
for (int i = 0; i < numConsumers; ++i) {
final Consumer c = new Consumer(i);
qs.add(c.getQ());
es.submit(c);
}
es.submit(new Producer(qs));
}
You are likely to get very few hits with this example as Random.nextInt() is used. If you want to get more hits reduce the range of the generated random numbers by calling Random.nextInt(int max) which generates numbers [0, max).
As you can see each Consumer has a queue of items to check and it blocks using the BlockingQueue API to wait for new items. The Producer puts the same item into each of the Consumer's queues in turn.
I have a thread with the following form:
each execution of each thread is supposed to run a function in the class. That function is completely safe to run by itself. The function returns a value, say an int.
After all threads have been executed, the function values need to be accumulated.
So, it goes (in pseudo-code) something like that:
a = 0
for each i between 1 to N
spawn a thread independently and call the command v = f(i)
when thread finishes, do safely: a = a + v
end
I am not sure how to use Java in that case.
The problem is not creating the thread, I know this can be done using
new Thread() {
public void run() {
...
}
}
the problem is accumulating all the answers.
Thanks for any info.
I would probably do something like:
public class Main {
int a = 0;
int[] values;
int[] results;
public Main() {
// Init values array
results = new int[N];
}
public int doStuff() {
LinkedList<Thread> threads = new LinkedList<Thread>();
for (final int i : values) {
Thread t = new Thread() {
public void run() {
accumulate(foo(i));
}
};
threads.add(t);
t.start();
}
for (Thread t : threads) {
try {
t.join();
} catch (InterruptedException e) {
// Act accordingly, maybe ignore?
}
}
return a;
}
synchronized void accumulate(int v) {
// Synchronized because a += v is actually
// tmp = a + v;
// a = tmp;
// which can cause a race condition AFAIK
a += v;
}
}
Use an ExecutorCompletionService, Executor, and Callable.:
Start with a Callable that calls your int function:
public class MyCallable implements Callable<Integer> {
private final int i;
public MyCallable(int i) {
this.i = i;
}
public Integer call() {
return Integer.valueOf(myFunction(i));
}
}
Create an Executor:
private final Executor executor = Executors.newFixedThreadPool(10);
10 is the maximum number of threads to execute at once.
Then wrap it in an ExecutorCompletionService and submit your jobs:
CompletionService<Integer> compService = new ExecutionCompletionService<Integer>(executor);
// Make sure to track the number of jobs you submit
int jobCount;
for (int i = 0; i < n; i++) {
compService.submit(new MyCallable(i));
jobCount++;
}
// Get the results
int a = 0;
for (int i = 0; i < jobCount; i++) {
a += compService.take().get().intValue();
}
ExecutorCompletionService allows you to pull tasks off of a queue as they complete. This is a little different from joining threads. Although the overall outcome is the same, if you want to update a UI as the threads complete, you won't know what order the threads are going to complete using a join. That last for loop could be like this:
for (int i = 0; i < jobCount; i++) {
a += compService.take().get().intValue();
updateUi(a);
}
And this will update the UI as tasks complete. Using a Thread.join won't necessarily do this since you'll be getting the results in the order that you call the joins, not the order that the threads complete.
Through the use of the executor, this will also allow you to limit the number of simultaneous jobs you're running at a given time so you don't accidentally thread-bomb your system.
I am using ThreadPoolExecutor in my multithreading program, I want each thread should have particular range of ID's if ThreadSize is set as 10 and Start = 1 and End = 1000 then each thread would have range of 100 id's(basically by dividing end range with thread size) that it can use without stepping on other threads.
Thread1 will use 1 to 100 (id's)
Thread2 will use 101 to 200 (id's)
Thread3 will use 201 to 300 (id's)
-----
-----
Thread10 will use 901 to 1000
I know the logic basically, the logic can be like this-
Each thread gets `N = (End - Start + 1) / ThreadSize` numbers.
Thread number `i` gets range `(Start + i*N) - (Start + i*N + N - 1)`.
As I am working with ThreadPoolExecutor for the first time, so I am not sure where should I use this logic in my code so that each Thread is Using a predefined ID's without stepping on other threads. Any suggestions will be appreciated.
public class CommandExecutor {
private List<Command> commands;
ExecutorService executorService;
private static int noOfThreads = 3;
// Singleton
private static CommandExecutor instance;
public static synchronized CommandExecutor getInstance() {
if (instance == null) {
instance = new CommandExecutor();
}
return instance;
}
private CommandExecutor() {
try {
executorService = Executors.newFixedThreadPool(noOfThreads);
} catch(Exception e) {
System.out.println(e);
}
}
// Get the next command to execute based on percentages
private synchronized Command getNextCommandToExecute() {
}
// Runs the next command
public synchronized void runNextCommand() {
// If there are any free threads in the thread pool
if (!(((ThreadPoolExecutor) executorService).getActiveCount() < noOfThreads))
return;
// Get command to execute
Command nextCommand = getNextCommandToExecute();
// Create a runnable wrapping that command
Task nextCommandExecutorRunnable = new Task(nextCommand);
executorService.submit(nextCommandExecutorRunnable); // Submit it for execution
}
// Implementation of runnable (the real unit level command executor)
private static final class Task implements Runnable {
private Command command;
public Task(Command command) {
this.command = command;
}
public void run() {
// Run the command
command.run();
}
}
// A wrapper class that invoked at every certain frequency, asks CommandExecutor to execute next command (if any free threads are available)
private static final class CoreTask implements Runnable {
public void run() {
CommandExecutor commandExecutor = CommandExecutor.getInstance();
commandExecutor.runNextCommand();
}
}
// Main Method
public static void main(String args[]) {
// Scheduling the execution of any command every 10 milli-seconds
Runnable coreTask = new CoreTask();
ScheduledFuture<?> scheduledFuture = Executors.newScheduledThreadPool(1).scheduleWithFixedDelay(coreTask, 0, 10, TimeUnit.MILLISECONDS);
}
}
Whether this is a good idea or not I will leave it for you to decide. But to give you a hand, I wrote a little program that does what you want... in my case I am just summing over the "ids".
Here is the code:
public class Driver {
private static final int N = 5;
public static void main(String args[]) throws InterruptedException, ExecutionException{
int startId = 1;
int endId = 1000;
int range = (1 + endId - startId) / N;
ExecutorService ex = Executors.newFixedThreadPool(N);
List<Future<Integer>> futures = new ArrayList<Future<Integer>>(N);
// submit all the N threads
for (int i = startId; i < endId; i += range) {
futures.add(ex.submit(new SumCallable(i, range+i-1)));
}
// get all the results
int result = 0;
for (int i = 0; i < futures.size(); i++) {
result += futures.get(i).get();
}
System.out.println("Result of summing over everything is : " + result);
}
private static class SumCallable implements Callable<Integer> {
private int from, to, count;
private static int countInstance = 1;
public SumCallable(int from, int to) {
this.from = from;
this.to = to;
this.count = countInstance;
System.out.println("Thread " + countInstance++ + " will use " + from + " to " + to);
}
// example implementation: sums over all integers between from and to, inclusive.
#Override
public Integer call() throws Exception {
int result = 0;
for (int i = from; i <= to; i++) {
result += i;
}
System.out.println("Thread " + count + " got result : " + result);
return result;
}
}
}
which produces the following output (notice that in true multi-thread fashion, you have print statements in random order, as the threads are executed in whatever order the system decides):
Thread 1 will use 1 to 200
Thread 2 will use 201 to 400
Thread 1 got result : 20100
Thread 3 will use 401 to 600
Thread 2 got result : 60100
Thread 4 will use 601 to 800
Thread 3 got result : 100100
Thread 5 will use 801 to 1000
Thread 4 got result : 140100
Thread 5 got result : 180100
Result of summing over everything is : 500500