Declaring a variable via Scanner? - java

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.

Related

When I run my methods it keeps repeating itself and doesn't move on java

Like the caption said the method "scanInput1" runs two times in a row when it should only run once. Then the method "arrayskapare" runs as intended but after that. instead of running the method "medelvarde" is jumps back and runs "scanInput1" again and again and again
import java.util.*;
class Heltalshanterare{
private static String scanInput1(){
System.out.print("Skriv in antal heltal: ");
Scanner scr = new Scanner(System.in);
String antalHeltal = scr.next();
try {
Integer.parseInt(antalHeltal);
}
catch (NumberFormatException e) {
System.out.println("Ogilitigt värde");
scanInput1();
}
return antalHeltal;
}
private static List<Integer> arrayskapare() {
int antalangivnatal = Integer.parseInt(scanInput1());
int noll = 1;
int heltal = 0;
String tal1 = "";
Scanner tal = new Scanner(System.in);
List<Integer> list = new ArrayList<>();
while (noll <= antalangivnatal) {
noll++;
heltal++;
System.out.print("ange heltal " + heltal + ": ");
tal1 = tal.next();
try {
int num = Integer.parseInt(tal1);
list.add(num);
} catch (NumberFormatException e) {
System.out.println("Ogiltigt värde");
noll--;
heltal--;
}
}
return list;
}
public static int medelvarde(){
int antalsiffror = arrayskapare().size();
int sum = 0;
for (int i : arrayskapare()){sum += i;}
int medelvärde = sum / antalsiffror;
System.out.println("medelvärdet av dina tal är " + medelvärde);
return medelvarde();
}
public static void main(String [] args){
scanInput1();
arrayskapare();
medelvarde();
}
}
Im sorry that the code is so long but I have been struggling with this for too long and I really need some help.
Your main method is calling each method just once, which is what you need. But it's not actually holding onto any of the values being returned. So the number of heltal (integers in English) is captured from the user but then never actually stored anywhere. And later an array of numbers is captured but not stored anywhere.
Your second, bigger problem is that your methods are then calling the earlier methods all over again. So instead of asking the user to type in the data just once, you're forcing them to answer the exact same questions multiple times.
A much tidier approach is to alter your methods so that they take the required data as a parameter. Which means your arrayskapare (array producer) method should take the antalHeltal (number of integers) value as a parameter, and then it won't need to call the scanInput1 method again. Same thing can be done for your medelvarde (mean value) method: have it take the array as a method parameter, so that it won't need to call arrayskapare.
With those changes your main method can simply look like this:
public static void main(String [] args){
int antalHeltal = scanInput1();
List<Integer> heltalArray = arrayskapare(antalHeltal);
int medelvardet = medelvarde(heltalArray);
System.out.println("Medelvärdet är " + medelvardet);
}
Now each method just gets called once and the data captured from the user gets stored into variables and passed along the river of methods until the final result is reached.

Easy way to generate unique random numbers (range) using threads? Java

I want to generate a list of unique random numbers from a given input range using threads in Java. For example, given a range of 1-4, I would run 4 threads and each thread would generate a random number such that no two threads would produce the same value twice. I presume I need to implement some synchronization or something? I've tried using Join() but it doesn't seem to work.
My constructor uses input values to populate an array list with a given range. In the run method, I generate a random value (from the same range) and check if it's in the list. If it is, I remove it from the list and print the value. The idea is that when another thread comes in, it can't generate that same value again.
Here is what I have so far:
public class Main {
public static void main(String[] args) {
randomThreadGen randomRange = new randomThreadGen(1, 2);
Thread thread1 = new Thread(randomRange);
Thread thread2 = new Thread(randomRange);
thread1.start();
try {
thread1.join();
} catch (InterruptedException e) {
}
thread2.start();
}
}
And this:
public class randomThreadGen implements Runnable {
private int lowerBound;
private int upperBound;
private final ArrayList<Integer> List = new ArrayList<Integer>();
public randomThreadGen(int lowerb, int upperb) {
this.lowerBound = lowerb;
this.upperBound = upperb;
for (int i = lowerb; i < upperb + 1; i++) { // populate list with values based on lower and upperbounds specified from main
List.add(i);
}
}
#Override
public void run() {
// generate random value
// check if in list. If in list, remove it
// print value
// otherwise try again
int val = ThreadLocalRandom.current().nextInt(lowerBound, upperBound+1); // generate random value based on lower and upper bound inputs from main
while(true){
if(List.contains(val)){
List.remove(new Integer(val));
System.out.println("Random value for " + Thread.currentThread().getName() + " " + val);
System.out.println("List values: " + List);
}
break;
}
}
}'''
This test case with a low range is to make testing easy. Sometimes it works, and Thread0 will generate a different value to Thread01 (1 and 2 or 2 and 1 for example). But sometimes it doesn't (seemingly they generate the same value, in which case my code only prints one value) For example, "Thread02 1" and nothing else.
Any ideas? Is there another way to do this other than join()?
It's quite an easy task. Just use a concurrent hashmap to prevent duplicates. Make sure to declare boundary int and the hashmap as final. Thread.join is needed to guarantee that the results will be printed after all threads have complete their work. There are other effective techniques to replace join but they are not for novices.
Try this:
import java.util.concurrent.ThreadLocalRandom;
import java.util.*;
import java.util.concurrent.*;
public class Main {
final static int low = 0;
final static int up = 5;
final static Set < Integer > inthashmap = ConcurrentHashMap.newKeySet();
// threadhashmap is needed to track down all threads generating ints
final static Set < Thread > threadhashmap = ConcurrentHashMap.newKeySet();
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < up - low + 1; i++) {
Thread t = new Thread() {
public void run() {
int randomNum;
try {
randomNum = ThreadLocalRandom.current().nextInt(low, up + 1);
inthashmap.add(randomNum);
System.out.println("A new random int generated : " + randomNum);
} finally {
}
}
};
threadhashmap.add(t);
t.start();
}
//by iterating through all threads in threadhashmap
// and joining them we guarantee that all threads were completed
// before we print the results of work of those threads (i.e. ints)
Iterator<Thread> iterator = threadhashmap.iterator();
while (iterator.hasNext())
iterator.next().join();
System.out.println("Unique ints from hashmap:");
inthashmap.forEach(System.out::println);
}
}
Output:
A new random int generated : 2
A new random int generated : 3
A new random int generated : 3
A new random int generated : 0
A new random int generated : 0
A new random int generated : 2
Unique ints from hashmap:
0
2
3

Updated code of NullPointerException problem with ConcurrentHashMap

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

NullPointerException in multi-threading simulation with HashMap

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.

Elevator: User input

I'm trying to make an application which copy an elevator operation (2 floors). But when I ask the user which floor he want to go, there are 2 differents possibilities. The first one, user enter a floor and the elevator move. The second one, after 10 secondes, still no response from user, at this point, the elevator have to close his door and turn off the light.
So my probleme is with the timeout, because I want my "while" to continue.
My main:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Scanner;
import java.util.Timer;
import java.util.TimerTask;
public class TP5 {
private String floorAsk = "";
TimerTask task = new TimerTask() {
public void run() {
if (floorAsk.equals("")) {
System.out.println("No response ...");
task.cancel();
}
}
};
public boolean getInput() throws Exception {
Timer timer = new Timer();
timer.schedule(task, 10 * 1000);
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
floorAsk = in.readLine();
timer.cancel();
System.out.println("Floor ask " + floorAsk);
return true;
}
/**
* main.
* #param args ceci est un String[]
*/
public static void main(String[] args) {
Controller c = new Controller();
Door p = new Door();
Light l = new Light();
Engine m = new Engine();
Button b = new CallButton();
while (true) {
Scanner sc = new Scanner(System.in);
System.out.println("What is your floor ?");
String actualFloorString = sc.nextLine();
int actualFloor = Integer.parseInt(actualFloorString);
if (actualFloor == 0 || etageAct == 1) {
System.out.println("You are at floor " + actualFloorString);
if (actualFloor != c.getShaft()) {
if (actualFloor > c.getShaft()) {
m.up();
} else if (actualFloor < c.getShaft()) {
m.down();
}
}
if (!l.isOn()) {
l.on();
}
if (!p.isOpen()) {
p.open();
}
System.out.println("Which floor do you want to go ?");
try {
(new TP5()).getInput();
} catch (Exception e) {
System.out.println(e);
}
System.out.println("test");
} else {
System.out.println("Please enter a valid floor (0 or 1)");
}
}
}
}
I try to use this solution: Time limit for an input
but I want to go back in my "while" and I don't know how to do it or if I'm using the right way to do it.
I also have some other class, Contoleur, Lumiere, Moteur, Porte, Bouton. But I haven't code the functions yet.
Thanks for you answer
EDIT
Ok I maybe find a way, I modify my code and now I have a function which take in parameter the scanner and a String:
public static int ask(Scanner sc, String t) {
System.out.println(t);
return sc.nextInt();
}
And I was wondering that maybe it's possible to put a timeout on a function. Do you know if it's possible ?
I would suggest the use of the Timer class.
https://docs.oracle.com/javase/7/docs/api/java/util/Timer.html
After a 10 second timeout, have the timer call a method that "closes" the elevator door.
The Timer can be canceled if the user inputs a valid integer. A new timer can be created when the door opens.
Edit: I didn't see you were already using the Timer object as I was scrolled down to the main method.

Categories

Resources