I am trying to do a multi thread simulator where there are workers (threads) and jobs to solve, so every thread has to solve a job and start to solve the next
in order, the integer of the job is the time in seconds that is required to solve the job, this is a simulation so the code prints the index of the thread with
the initialization time of the job but it hasn't to be sleeping that number of seconds.
The problem is that i'm getting a NullPointerException only when there are a lot of jobs with the same number like
4 12 (4 threads for 12 jobs)
1 1 1 1 1 1 1 1 1 1 1 1 (12 jobs that require 1 second to be completed) it launches the exception in this part:
if (workersReady.size()>1) {
bestWorker = workersReady.iterator().next();
workersReady.remove(bestWorker);
workersReadyAtTimeT.remove(currentTime);
workersReadyAtTimeT.put(currentTime,workersReady);
nextTimesQueue.add(currentTime);
The input has to be like this:
First line:
2 5 It means that there are two threads(workers) for 5 jobs
Press enter and write the second line:
1 2 3 4 5 This is the jobs that are an integer which means the time cost of processing that job so the output after press enter will be this:
0 0 The two threads try to simultaneously take jobs from the list, so thread with index 0 actually
takes the first job and starts working on it at the moment 0
1 0 Thread with index 1 takes the first job and starts working on it at the moment 0
0 1 After 1 second, thread 0 is done with the first job and takes the third job from the list, and
starts processing it immediately at time 1.
1 2 One second later, thread 1 is done with the second job and takes the fourth job from the list, and starts processing it immediately at time 2
0 4 Finally, after 2 more seconds, thread 0 is done with the third job and takes the fifth job from the list, and starts processing it immediately at time 4
This is the code:
import java.io.*;
import java.util.HashMap;
import java.util.HashSet;
import java.util.PriorityQueue;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.concurrent.ConcurrentHashMap;
public class JobQueue {
private int numWorkers;
private int[] jobs;
private int[] assignedWorker;
private long[] startTime;
private FastScanner in;
private PrintWriter out;
public static void main(String[] args) throws IOException {
new JobQueue().solve();
}
private void readData() throws IOException {
numWorkers = in.nextInt();
int m = in.nextInt();
jobs = new int[m];
for (int i = 0; i < m; ++i) {
jobs[i] = in.nextInt();
}
}
private void writeResponse() {
for (int i = 0; i < jobs.length; ++i) {
out.println(assignedWorker[i] + " " + startTime[i]);
}
}
private void assignJobs() {
// TODO: replace this code with a faster algorithm.
assignedWorker = new int[jobs.length];
startTime = new long[jobs.length];
PriorityQueue<Integer> nextTimesQueue = new PriorityQueue<Integer>();
ConcurrentHashMap<Integer, Set<Integer>> workersReadyAtTimeT = new ConcurrentHashMap<Integer,Set<Integer>>();
long[] nextFreeTime = new long[numWorkers];
int duration = 0;
int bestWorker = 0;
for (int i = 0; i < jobs.length; i++) {
duration = jobs[i];
if(i<numWorkers) {
bestWorker = i;
nextTimesQueue.add(duration);
addToSet(workersReadyAtTimeT, duration, i,0);
}else {
int currentTime = nextTimesQueue.poll();
Set<Integer> workersReady = workersReadyAtTimeT.get(currentTime);
if (workersReady.size()>1) {
bestWorker = workersReady.iterator().next();
workersReady.remove(bestWorker);
workersReadyAtTimeT.remove(currentTime);
workersReadyAtTimeT.put(currentTime,workersReady);
nextTimesQueue.add(currentTime);
} else {
bestWorker = workersReady.iterator().next();
workersReadyAtTimeT.remove(currentTime);
nextTimesQueue.add(currentTime+duration);
addToSet(workersReadyAtTimeT, duration, bestWorker, currentTime);
}
}
assignedWorker[i] = bestWorker;
startTime[i] = nextFreeTime[bestWorker];
nextFreeTime[bestWorker] += duration;
}
}
private void addToSet(ConcurrentHashMap<Integer, Set<Integer>> workersReadyAtTimeT, int duration, int worker, int current) {
if(workersReadyAtTimeT.get(current+duration)==null) {
HashSet<Integer> s = new HashSet<Integer>();
s.add(worker);
workersReadyAtTimeT.put(current+duration, s);
}else {
Set<Integer> s = workersReadyAtTimeT.get(current+duration);
s.add(worker);
workersReadyAtTimeT.put(current+duration,s);
}
}
public void solve() throws IOException {
in = new FastScanner();
out = new PrintWriter(new BufferedOutputStream(System.out));
readData();
assignJobs();
writeResponse();
out.close();
}
static class FastScanner {
private BufferedReader reader;
private StringTokenizer tokenizer;
public FastScanner() {
reader = new BufferedReader(new InputStreamReader(System.in));
tokenizer = null;
}
public String next() throws IOException {
while (tokenizer == null || !tokenizer.hasMoreTokens()) {
tokenizer = new StringTokenizer(reader.readLine());
}
return tokenizer.nextToken();
}
public int nextInt() throws IOException {
return Integer.parseInt(next());
}
}
}
Edit: I used a ConcurentHashMap and still launching NullPointer
Related
I am trying to do a multi thread simulator where there are workers (threads) and jobs to solve, so every thread has to solve a job and start to solve the next
in order, the integer of the job is the time in seconds that is required to solve the job, this is a simulation so the code prints the index of the thread with
the initialization time of the job but it hasn't to be sleeping that number of seconds.
The problem is that i'm getting a NullPointerException only when there are a lot of jobs with the same number like
4 12 (4 threads for 12 jobs)
1 1 1 1 1 1 1 1 1 1 1 1 (12 jobs that require 1 second to be completed) it launches the exception in this part:
if (workersReady.size()>1) {
bestWorker = workersReady.iterator().next();
workersReady.remove(bestWorker);
workersReadyAtTimeT.remove(currentTime);
workersReadyAtTimeT.put(currentTime,workersReady);
nextTimesQueue.add(currentTime);
The input has to be like this:
First line:
2 5 It means that there are two threads(workers) for 5 jobs
Press enter and write the second line:
1 2 3 4 5 This is the jobs that are an integer which means the time cost of processing that job so the output after press enter will be this:
0 0 The two threads try to simultaneously take jobs from the list, so thread with index 0 actually
takes the first job and starts working on it at the moment 0
1 0 Thread with index 1 takes the first job and starts working on it at the moment 0
0 1 After 1 second, thread 0 is done with the first job and takes the third job from the list, and
starts processing it immediately at time 1.
1 2 One second later, thread 1 is done with the second job and takes the fourth job from the list, and starts processing it immediately at time 2
0 4 Finally, after 2 more seconds, thread 0 is done with the third job and takes the fifth job from the list, and starts processing it immediately at time 4
This is the code:
import java.io.*;
import java.util.HashMap;
import java.util.HashSet;
import java.util.PriorityQueue;
import java.util.Set;
import java.util.StringTokenizer;
public class JobQueue {
private int numWorkers;
private int[] jobs;
private int[] assignedWorker;
private long[] startTime;
private FastScanner in;
private PrintWriter out;
public static void main(String[] args) throws IOException {
new JobQueue().solve();
}
private void readData() throws IOException {
numWorkers = in.nextInt();
int m = in.nextInt();
jobs = new int[m];
for (int i = 0; i < m; ++i) {
jobs[i] = in.nextInt();
}
}
private void writeResponse() {
for (int i = 0; i < jobs.length; ++i) {
out.println(assignedWorker[i] + " " + startTime[i]);
}
}
private void assignJobs() {
// TODO: replace this code with a faster algorithm.
assignedWorker = new int[jobs.length];
startTime = new long[jobs.length];
PriorityQueue<Integer> nextTimesQueue = new PriorityQueue<Integer>();
HashMap<Integer, Set<Integer>> workersReadyAtTimeT = new HashMap<Integer,Set<Integer>>();
long[] nextFreeTime = new long[numWorkers];
int duration = 0;
int bestWorker = 0;
for (int i = 0; i < jobs.length; i++) {
duration = jobs[i];
if(i<numWorkers) {
bestWorker = i;
nextTimesQueue.add(duration);
addToSet(workersReadyAtTimeT, duration, i,0);
}else {
int currentTime = nextTimesQueue.poll();
Set<Integer> workersReady = workersReadyAtTimeT.get(currentTime);
if (workersReady.size()>1) {
bestWorker = workersReady.iterator().next();
workersReady.remove(bestWorker);
workersReadyAtTimeT.remove(currentTime);
workersReadyAtTimeT.put(currentTime,workersReady);
nextTimesQueue.add(currentTime);
} else {
bestWorker = workersReady.iterator().next();
workersReadyAtTimeT.remove(currentTime);
nextTimesQueue.add(currentTime+duration);
addToSet(workersReadyAtTimeT, duration, bestWorker, currentTime);
}
}
assignedWorker[i] = bestWorker;
startTime[i] = nextFreeTime[bestWorker];
nextFreeTime[bestWorker] += duration;
}
}
private void addToSet(HashMap<Integer, Set<Integer>> workersReadyAtTimeT, int duration, int worker, int current) {
if(workersReadyAtTimeT.get(current+duration)==null) {
HashSet<Integer> s = new HashSet<Integer>();
s.add(worker);
workersReadyAtTimeT.put(current+duration, s);
}else {
Set<Integer> s = workersReadyAtTimeT.get(current+duration);
s.add(worker);
workersReadyAtTimeT.put(current+duration,s);
}
}
public void solve() throws IOException {
in = new FastScanner();
out = new PrintWriter(new BufferedOutputStream(System.out));
readData();
assignJobs();
writeResponse();
out.close();
}
static class FastScanner {
private BufferedReader reader;
private StringTokenizer tokenizer;
public FastScanner() {
reader = new BufferedReader(new InputStreamReader(System.in));
tokenizer = null;
}
public String next() throws IOException {
while (tokenizer == null || !tokenizer.hasMoreTokens()) {
tokenizer = new StringTokenizer(reader.readLine());
}
return tokenizer.nextToken();
}
public int nextInt() throws IOException {
return Integer.parseInt(next());
}
}
}
Edit: I used a ConcurentHashMap and still launching NullPointer
HashMap is not threadsafe.
If you interact with a hashmap from multiple threads without 'external' synchronization, then the spec of HashMap says anything is fair game. If your computer starts playing Yankee Doodle Dandee, that would be compatible with the spec, and no bug report would be accepted on that account.
In other words, you MUST take care of this yourself.
Usually, the right move is to use ConcurrentHashMap instead (from the extremely useful java.util.concurrent package), and so it is here.
If you must, you can externally synchronize as well. For example:
synchronized (workersReady) {
// interact with workersReady here
}
but synchronized is a pretty clumsy cudgel to use here, and may well remove most/all of the benefits of trying to multithread this stuff.
Note that a 'pool of workers' sounds more like a job for e.g. ExecutorPool. Make sure to check the j.u.c package, I'm pretty sure it has something much more appropriate so you can delete most of what you wrote and use a carefully tweaked solution, pre-tested and optimized.
Maybe look at ConcurrentHashMap.
public static void main(String[] args) {
List<String> data = new ArrayList<>();
for (int i = 0; i < 10000000; i++) {
data.add("data" + i);
}
System.out.println("parallel stream start time" + System.currentTimeMillis());
data.parallelStream().forEach(x -> {
System.out.println("data -->" + x);
});
System.out.println("parallel stream end time" + System.currentTimeMillis());
System.out.println("simple stream start time" + System.currentTimeMillis());
data.stream().forEach(x -> {
System.out.println("data -->" + x);
});
System.out.println("simple stream end time" + System.currentTimeMillis());
System.out.println("normal foreach start time" + System.currentTimeMillis());
for (int i = 0; i < data.size(); i++) {
System.out.println("data -->" + data.get(i));
}
System.out.println("normal foreach end time" + System.currentTimeMillis());
}
Output
parallel stream start time 1501944014854
parallel stream end time 1501944014970
simple stream start time 1501944014970
simple stream end time 1501944015036
normal foreach start time 1501944015036
normal foreach end time 1501944015040
Total time taken
Simple stream -> 66
Parellem stream -> 116
simple foreach -> 4
In many blogs written that parallelStream is executing by parallel by internally managed distributed task among thread and collect automatically..
But as per above experiment it is clearly notice that Parallel Stream taking more time then simple stream and normal foreach.
Why it is taking more time if it is executed parallel? Is it good to use in project as this feature is downgrading performance?
Thanks in Advance
Your tests are based on I/O operations (the most expensive operation)
If you want to use parallel streams you have to take the thread creation time overhead into account. So only if your operation benefits from that then use it (that is the case for heavy operations). If not, then just use normal streams or a regular for-loop.
Basic rules for measurement:
Don't use I/O operation.
Repeat the same test more then just once.
So if we have to re-formulate the test scenarios again, then we probably have a test helper class defined as follows:
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class Benchmark {
public static <T> T performTest(Callable<T> callable, int iteration, String name) throws Exception {
Map<String, Iteraion> map = new HashMap<>();
T last = null;
for (int i = 0; i < iteration; i++) {
long s = System.nanoTime();
T temp = callable.call();
long f = System.nanoTime();
map.put(UUID.randomUUID().toString(), new Iteraion(s, f));
if (i == iteration - 1) {
last = temp;
}
}
System.out.print("TEST :\t" + name + "\t\t\t");
System.out.print("ITERATION: " + map.size());
long sum = 0l;
for (String i : map.keySet()) {
sum += (map.get(i).finish - map.get(i).start);
}
long avg = (sum / map.size()) / 1000000;
System.out.println("\t\t\tAVERAGE: " + avg + " ms");
return last;
}
public interface Callable<T> {
T call() throws Exception;
}
static class Iteraion {
Long start;
Long finish;
public Iteraion(Long s, Long f) {
start = s;
finish = f;
}
}
}
Now we can perform the same test more then once using different operation. The following code shows test performed using two different scenarios.
import java.util.ArrayList;
import java.util.List;
import static java.lang.Math.*;
#SuppressWarnings("unused")
public class Test {
public static void main(String[] args) {
try {
final int iteration = 100;
final List<String> data = new ArrayList<>();
for (int i = 0; i < 10000000; i++) {
data.add("data" + i);
}
/**
* Scenario 1
*/
Benchmark.performTest(new Callable<Void>() {
#Override
public Void call() throws Exception {
data.parallelStream().forEach(x -> {
x.trim();
});
return (Void) null;
}
}, iteration, "PARALEL_STREAM_ASSIGN_VAL");
Benchmark.performTest(new Callable<Void>() {
#Override
public Void call() throws Exception {
data.stream().forEach(x -> {
x.trim();
});
return (Void) null;
}
}, iteration, "NORMAL_STREAM_ASSIGN_VAL");
Benchmark.performTest(new Callable<Void>() {
#Override
public Void call() throws Exception {
for (int i = 0; i < data.size(); i++) {
data.get(i).trim();
}
return (Void) null;
}
}, iteration, "NORMAL_FOREACH_ASSIGN_VAL");
/**
* Scenario 2
*/
Benchmark.performTest(new Callable<Void>() {
#Override
public Void call() throws Exception {
data.parallelStream().forEach(x -> {
Integer i = Integer.parseInt(x.substring(4, x.length()));
double d = tan(atan(tan(atan(i))));
});
return (Void) null;
}
}, iteration, "PARALEL_STREAM_COMPUTATION");
Benchmark.performTest(new Callable<Void>() {
#Override
public Void call() throws Exception {
data.stream().forEach(x -> {
Integer i = Integer.parseInt(x.substring(4, x.length()));
double d = tan(atan(tan(atan(i))));
});
return (Void) null;
}
}, iteration, "NORMAL_STREAM_COMPUTATION");
Benchmark.performTest(new Callable<Void>() {
#Override
public Void call() throws Exception {
for (int i = 0; i < data.size(); i++) {
Integer x = Integer.parseInt(data.get(i).substring(4, data.get(i).length()));
double d = tan(atan(tan(atan(x))));
}
return (Void) null;
}
}, iteration, "NORMAL_FOREACH_COMPUTATION");
} catch (Exception e) {
e.printStackTrace();
}
}
}
The first scenario performs the same test using the trim() method 100 times for a list that contains 10_000_000 elements and therefore it uses a parallel stream, then a normal stream and last the old school for loop.
The second scenario performs some relatively heavy operations like tan(atan(tan(atan(i)))) for the same list with the same technique as in the first scenario.
The results are:
// First scenario, average times
Parallel stream: 78 ms
Regular stream: 113 ms
For-loop: 110 ms
// Second scenario, average times
Parallel stream: 1397 ms
Regular stream: 3866 ms
For-loop: 3826 ms
Note that you can debug the above code, then you notice that for parallel streams the program creates three extra threads under name [ForkJoinPool-1], [ForkJoinPool-2] and [ForkJoinPool-3].
Edit:
The sequential streams and the for-loop use the caller's thread.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
Implement producer consumer problem using threads in Java. Producers and consumers share a buffer, producers put elements in buffer and consumers consume elements from the shared buffer. If the buffer is full producers should wait till consumers take out elements, similarly consumers should wait till producers put elements if the buffer is empty.
Your program should accept the following inputs:
m: the number of producer threads
n: the number of consumer threads
k: the size of the bounded buffer
Your code should prompt for the above inputs in that order. You can assume that a valid integer is provided by the user for each of these. You will need to spawn m Producer threads and n Consumer threads. Each producer generates 20 integers ranging between 0 and 9 and puts them in the buffer. After putting a number in the buffer, it prints its id along with the generated number. The producer sleeps for a random amount of time before repeating the number generating cycle again. Each consumer takes a number from the buffer then prints its id along with the value it got. Then, it sleeps for a random amount of time before reading from the buffer again.
A sample output of the program is:
Producer #2 put: 1
Producer #1 put: 4
Consumer #3 got: 1
Producer #1 put: 3
Consumer #3 got: 4
Consumer #3 got: 3
...
i have this problem. it is clear that the array of buffer is a global variable for two method because of that array is shared with Producer & Consumer. so? Unfortunately i have no idea how to do this project. anybody have an idea?
import java.security.SecureRandom;
import java.util.concurrent.*;
/**
* Created by Leon.H on 2016/1/13.
*/
public class ProducerConsumer {
private int producerNumber = 0;
private int consumerNumber = 0;
private int bufferSize = 0;
private final int seconds;
public ProducerConsumer(int producerNumber, int consumerNumber, int bufferSize, int seconds) {
this.producerNumber = producerNumber;
this.consumerNumber = consumerNumber;
this.bufferSize = bufferSize;
this.seconds = seconds;
System.out.println(this.producerNumber+ ": the number of producer threads");
System.out.println(this.consumerNumber+ ": the number of consumer threads");
System.out.println(this.bufferSize+ ": the number of producer threads");
}
public void process() throws InterruptedException {
ExecutorService producerExecutorService = Executors.newFixedThreadPool(this.producerNumber);
ExecutorService consumerExecutorService = Executors.newFixedThreadPool(this.consumerNumber);
BlockingQueue<Integer> integers = new ArrayBlockingQueue<Integer>(this.bufferSize);
for (int i = 0; i < this.producerNumber; i++) {
producerExecutorService.execute(new ProducerTask(integers));
}
for (int i = 0; i < this.consumerNumber; i++) {
consumerExecutorService.execute(new ConsumerTask(integers));
}
producerExecutorService.shutdown();
consumerExecutorService.shutdown();
//let the program run 10 seconds
producerExecutorService.awaitTermination(this.seconds, TimeUnit.SECONDS);
consumerExecutorService.awaitTermination(this.seconds, TimeUnit.SECONDS);
}
private class ProducerTask implements Runnable {
private final BlockingQueue<Integer> integers;
public ProducerTask(BlockingQueue<Integer> integers) {
this.integers = integers;
}
public void run() {
while (true) {
Integer content = new SecureRandom().nextInt(1000);
System.out.println("Producer #" + Thread.currentThread().getId() + " put: " + content);
integers.offer(content);
try {
Thread.sleep(new SecureRandom().nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
private class ConsumerTask implements Runnable {
private final BlockingQueue<Integer> integers;
public ConsumerTask(BlockingQueue<Integer> integers) {
this.integers = integers;
}
public void run() {
while (true) {
try {
System.out.println("Consumer #" + Thread.currentThread().getId() + " get: " + integers.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
Thread.sleep(new SecureRandom().nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
import org.junit.Test;
/**
* Created by Leon.H on 2016/1/13.
*/
public class ProducerConsumerTest {
#Test
public void oneProducerOneConsumerSizeOne() throws InterruptedException {
int ProducerNumber = 1;
int ConsumerNumber = 1;
int size = 1;
int seconds=5;
ProducerConsumer producerConsumer = new ProducerConsumer(ProducerNumber, ConsumerNumber, size, seconds);
producerConsumer.process();
}
#Test
public void twoProducerThreeConsumerSizeThree() throws InterruptedException {
int ProducerNumber = 2;
int ConsumerNumber = 3;
int size = 3;
int seconds = 5;
ProducerConsumer producerConsumer = new ProducerConsumer(ProducerNumber, ConsumerNumber, size, seconds);
producerConsumer.process();
}
#Test
public void twoHundredProducerThreeConsumerSizeThree() throws InterruptedException {
int ProducerNumber = 20;
int ConsumerNumber = 3;
int size = 3;
int seconds=5;
ProducerConsumer producerConsumer = new ProducerConsumer(ProducerNumber, ConsumerNumber, size, seconds);
producerConsumer.process();
}
}
I'm trying to set my int "n" to be defined by a users input. however it is never set and I'm not sure what's wrong. I'M NOT very good at java and this IS homework. I think my problem is very basic but I'm stuck.
So, to restate my question. Why can't I set my int n to be a user input? The "n" problem isn't the actual homework but in order for my homework to work correctly, "n" has to be set.
package printer.java;
import java.util.Queue;
import java.util.LinkedList;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Random;
import java.util.Scanner;
public class PrinterJava {
// Declaring ints needed
int count = 0;
int jobCount = 0;
int done = 0;
int time = 0;
int jobTimerDelay = 1000;
int jobTimerPeriod = 1000;
int timeTimerDelay = 1000;
int timeTimerPeriod = n * 60 * 1000;
// declaring timers needed
Timer jobTimerTimer = new Timer();
Timer timeTimerTimer = new Timer();
// This is a timer that is supposed to create new "pages" every 5 seconds.
//the pages have to be a random "size between 1 and 5 pages long"
public void jobTimer() {
jobTimerTimer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
count++;
Random dom = new Random();
int p = dom.nextInt(5) + 1;
if (count % 5 == 0) {
pages page = new pages(); // Creates a new page every 5 seconds
page.pages = p;
jobCount++;
jobQueue.offer(page); // pushes the newly created pages into the queue
System.out.println("A new Job has been created! Job queue size: " + jobQueue.size());
System.out.println("Total Jobs created: " + jobCount);
} else if (!jobQueue.isEmpty() && count > 2 && count % 2 == 0) {
done++;
jobQueue.remove();
System.out.println("Job printed successfully! total jobs printed: " + done);
}
}
}, jobTimerDelay, jobTimerPeriod);
}
// this is the queue that holds the pages
Queue<Object> jobQueue = new LinkedList<Object>();
public class pages { // pages
int pages;
// constructor
public pages() {
}
public pages(int NumPages) {
this.pages = NumPages;
}
}
public void timerTwo() {
timeTimerTimer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
PrinterJava runOne = new PrinterJava(); // creats an instance of my page creator
runOne.jobTimer();
System.out.println("Please Enter Run time in minutes as an integer: ");
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
}
}, timeTimerDelay, timeTimerPeriod);
}
public static void main(String[] args) {
PrinterJava runTwo = new PrinterJava(); // creats an instance of my page creator
runTwo.timerTwo();
}
}
This line won't compile because n is not defined yet:
int timeTimerPeriod = n * 60 * 1000;
However, if it would this won't work as expected either:
timeTimerTimer.scheduleAtFixedRate(new TimerTask() {...}, timeTimerDelay, timeTimerPeriod);
Because n is defined inside TimerTask.run() method. To solve this consider make this changes:
int timeTimerPeriod = 60 * 1000; // instance variable
int n = 0;
...
public void timerTwo() {
System.out.println("Please Enter Run time in minutes as an integer: ");
Scanner scan = new Scanner(System.in);
n = scan.nextInt(); // <-- read n here for first time
timeTimerTimer.scheduleAtFixedRate(new TimerTask() {...}, timeTimerDelay, timeTimerPeriod * n);
}
When you say int n you are declaring a new variable, so after that next line you don't have a reference to it anymore. Also, i don't see n declared as an instance variable or anywhere else.
What if you set a breakpoint right after the line int n = scan.nextInt(); and see if it is being set there (alternatively you could use System.out.println() to print it out.
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