For and While Loop - java

I have a program that runs simultaneously and I have this problem where I want to stop the thread but the for loop/while loop doesn't get cancelled once I once I click enter
If I take the for loop out of the while loop, the program actually responds to the enter and shuts down.
class MyNumber extends Thread {
private volatile boolean processing = true;
public void run() {
while (processing) {
// Once I take this for loop out(put // beside it like right now), the enter key to stop the program then does work.
//for(int i = 1; i<27; i++){
System.out.println("Letter " + "i");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// }
}
}
public void permSleep() {
processing = false;
}
}
public class LetterNumber {
public static void main(String[] args) {
MyNumber num1 = new MyNumber();
num1.start();
System.out.println("Hit enter to stop the Numbers!");
Scanner shutter1 = new Scanner(System.in);
shutter1.nextLine();
num1.permSleep();
}
}
Why does the for loop cause the program to not shutdown?

I'm not really clear on what you're asking. However, if you're expecting that the while and for loops will both terminate as soon as processing is set to true, that isn't what happens. A while will execute the statement in the body (i.e. the for loop), then it will test the condition (processing == true), then if it's true, it executes the statement again, and then tests the condition again. It doesn't test it while the for loop is executing. It doesn't "notice" when the processing variable is set. So when processing is set to true, the for loop will keep going until it's done, which could be another 26 seconds.
To fix this simply, add
if (!processing)
break;
inside the for loop. Now the processing flag will be tested each time through the for loop. (If it were me, I'd put a "label" on the while loop and use that to break out of both loops.) Another way to fix it:
for(int i = 1; i<27 && processing; i++){
which means the for loop will continue only as long as processing is true.
Note: These solutions will still not test processing while the sleep(1000) is going on. So the program could still pause up to 1 second before it terminates. If you really want a solution that will terminate the sleep, you'll have use interrupt or some other concurrency feature.

It should work. Your for loop takes about 27 seconds to finish. It should come out of that after the for loop has finished.

Related

How to make a timer using Thread.sleep() while waiting for console input?

I'm trying to write a program that asks simple questions with a time limit on them.
So far I have the following:
public static void main(String[]args) throws IOException, InterruptedException{
Thread thread = new Thread();
Scanner scan = new Scanner(System.in);
System.out.println("1. What is 1+1?");
System.out.println("a. 2\tb. Cannot Be.\tc. 3\td. All of the above.");
String question1 = scan.next();
for(int i = 3; i>=0; i--){
System.out.print("\b"+i);
Thread.sleep(1000);
}
}
This properly asks the question and takes the answer, but it doesn't put a time limit on input and counts down from 3 to 0 after the input is given. What am I doing wrong?
This can be done using a little bit of black multithreading magic.
First, you'll need two threads like this:
Thread thread1 = Thread.currentThread();
Thread thread2 = new Thread(() -> {
try {
for (int seconds = 3; seconds > 0; seconds--) {
System.out.println(seconds+" second"+(seconds == 1 ? "s" : "")+" left");
Thread.sleep(1000);
}
System.out.println("Time's up!");
thread1.stop();
}catch(InterruptedException weCanIgnoreThisException){}
});
where thread1 is the thread that asks the question and thread2 is the countdown.
Then what is left is to ask the question. Don't forget to start() thread2 before asking for input and to stop() it after receiving the input!
System.out.println("1. What is 1+1?");
System.out.println("a. 2\tb. Cannot Be.\tc. 3\td. All of the above.");
thread2.start();
String answer = scan.next();
thread2.stop();
Alright, so here's why I used the deprecated method Thread#stop().
The official documentation of java.lang.Thread explains why is stop() deprecated and what circumstances make it screw up programs:
Stopping a thread with Thread.stop causes it to unlock all of the monitors that it has locked (as a natural consequence of the unchecked ThreadDeath exception propagating up the stack). If any of the objects previously protected by these monitors were in an inconsistent state, the damaged objects become visible to other threads, potentially resulting in arbitrary behavior.
In short, if a thread is stop()ped while it's locked on an object using a synchronized block or method, the lock on the object is released in a dangerously abrupt manner. Since asking multiple choice questions and placing a time limit on input doesn't require a thread to be synchronized on something, we can ignore this.
I would create separate functions to call during the loop, so you don't have a long winded declaration of global variables and such. If you need to control what is called randomly, then you can put a rand in a function and use one global that way, or you can simply put them in a order you want it to be called and completed as.
As you rightly guessed, you need two separate threads running like in the below explanation & code.
The below explanation will provide you more details on what and how you need to do with the two threads.
(1) Thread 1: Timer thread (Inner class implements Runnable) runs in a separate thread and counts the seconds while waiting for the user's input. Once user enters the input this thread needs to be stopped using a signal (stopTimer variable acts as a signal), ensure that stopTimer variable is volatile (to receive the data written by Thread2), otherwise this thread will wait infinitely.
(2) Thread 2: This is the main thread which waits for the user's input. Once the user inputs the data, this main thread signals to stop the Timer thread using a separate method call - signalStopTimer()
public class TimerTest {
public static class Timer implements Runnable {
private volatile boolean stopTimer = false;
private long timerMilliSeconds =0;
#Override
public void run() {
try {
while(!stopTimer) {
Thread.sleep(1000);
timerMilliSeconds = timerMilliSeconds+1000;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void signalStopTimer() {
stopTimer = true;
}
//this method will be helpful to find the elapsed time in seconds
public long getTotalTimeInSeconds() {
return timerMilliSeconds/1000;
}
}
public static void main(String[] args) {
TimerTest.Timer timer = new TimerTest.Timer();
//Start the Timer Thread now
Thread thread = new Thread(timer);
thread.start();
Scanner scan = new Scanner(System.in);
System.out.println("1. What is 1+1?");
System.out.println("a. 2\tb. Cannot Be.\tc. 3\td. All of the above.");
String input = scan.next();
//received the input, signal to stop timer
timer.signalStopTimer();
System.out.println(" input is:"+input+" seconds");
System.out.println(" total time :"+timer.getTotalTimeInSeconds());
}
}
In case you only need to count the time it took until user put his input, the better way and the easiest way is to use System.currentTimeMillis().
before the scan code you can save the current time in a variable (Long), then in while loop (when the loop condition will be stopped when the user put his input) in the end of the loop just save the same way mentioned above the current time in millisecond and then all left is subtraction.
if this is your direction let me know i can supply a code for that ;)

Why does this code work with if statement but not while loop?

public void timerCallback()
{
if (count < 8)
{
System.out.println("My timer woke up!");
this.setOutputState(this.pinNumber, this.pinState);
this.pinState = !this.pinState;
this.setTimer(this.timerDelay);
count++;
}else
{
this.stopMonitoring();
}
}
That works in the sense that it prints the statement (with the delay) 8 times then terminates the program. Now this:
public void timerCallback()
{
while (count < 8)
{
System.out.println("My timer woke up!");
this.setOutputState(this.pinNumber, this.pinState);
this.pinState = !this.pinState;
this.setTimer(this.timerDelay);
count++;
}
this.stopMonitoring();
}
That code just prints the statement 8 times at once, then terminates. Why is that?
The purpose of the if/else in the original version is to give the timer eight chances to "wake up" and toggle pin state before invoking stopMonitoring(). Printing the message is secondary. So the if/else checks to see if timerCallback() has been called 8 times. If it hasn't, ok, print the message and give it another chance.
By substituting a while, you just end up printing the message 8 times, toggling pin state back and forth rapidly without checking to see if it helps, and then dropping into stopMonitoring(). So you stop monitoring after the first call to timerCallback(), not the eighth.

Concurrent puzzle solving: Java Concurrency - Cyclicbarrier. Correct usage?

I'm trying to write a program to solve 2 puzzles who can't be solved independently from eachother, but have the same solution. My idea is that they both run in a seperate thread until they stop finding new pieces of information. Then they communicate what they have found by updating some shared state variables and continue if something was written by either one of them to the shared state.
I think a CyclicBarrier is the appropriate mechanism to use here. This is my code (which is running concurrently in 2 threads:
while (true) {
doSolvingLogicHere();
shareUpdates(); // this method updates the shared state variable and is synhronized
int count;
int updates = 0;
try {
count = writeBarrier.await();
updates = threadsUpdatedSomething;
if (count == 0) {
writeBarrier.reset();
threadsUpdatedSomething = 0; //'reset' the shared value
}
} catch (InterruptedException ex) {
Logger.getLogger(TwinSolver.class.getName()).log(Level.SEVERE, null, ex);
} catch (BrokenBarrierException ex) {
Logger.getLogger(TwinSolver.class.getName()).log(Level.SEVERE, null, ex);
}
if (updates == 0) { //no thread updated something
break;
} else { // at least one of the threads updated something, solving should continue in both threads
readUpdates();
}
}
ThreadsUpdatedSomething is a shared integer which is incremented in the 'ShareUpdates()' if anything at all was updated by the threads. When both threads didn't find anything new in the iteration, this means that they never will find anything new and the whole loop should be stopped for both threads. That's why I'm checking for it to be zero.
I would expect them to both stop when both threads did not write any new information in the shared state variables. But when running the program, one of the threads stop, while the other one keeps going. When debugging the program and setting breakpoints at 'readUpdates()' line, the program works as expected.
Is this the correct way for handling such a concurrent 'solving' loop? And in case it is correct, where is the error in my code?
Thanks for the help!
EDIT: Small mistake corrected. 'updates = threadsUpdatedSomething;' now at the correct place
As per API , await returns
the arrival index of the current thread, where index getParties() - 1 indicates the first to arrive and zero indicates the last to arrive
count = writeBarrier.await();
Being said , So only one of the Thread would receive the 0 . And only one thread would set the updates value to 0. Thats why the last arrived thread stopped and other one not stopped.
As per your statements , you need to stop the threads when you find both threads not updated the threadsUpdatedSomething. i assumed that time threadsUpdatedSomething would be zero.
If not you have to change the logic , some how to find when the condition has to be break and apply it
while (true) {
doSolvingLogicHere();
shareUpdates(); // this method updates the shared state variable and is synhronized
int count;
int updates = 0;
try {
writeBarrier.await();
if (threadsUpdatedSomething == 0) {
updates = threadsUpdatedSomething;
writeBarrier.reset();
threadsUpdatedSomething -= 2; //'reset' the counter by decrementing 2
}
} catch (InterruptedException ex) {
Logger.getLogger(TwinSolver.class.getName()).log(Level.SEVERE, null, ex);
} catch (BrokenBarrierException ex) {
Logger.getLogger(TwinSolver.class.getName()).log(Level.SEVERE, null, ex);
}
if (updates == 0) { //no thread updated something
break;
} else { // at least one of the threads updated something, solving should continue in both threads
readUpdates();
}
}
Also Don't forgot to set the break conditions in exception cases if required.

How do I check how many events are happening within 2 seconds? (timer)

I need to check how many events are detected within 2 seconds. I have the timer working and I have everything else working...but I ran into a problem: the loop only checks one time, per second and I can't seem to figure out how to fix that. I need it to check constantly during these two seconds to see how many events there were in total!
Here is what I have:
int seconds = 0;
System.out.println("Seconds: " + seconds);
while(seconds < 2)
{
//Wait 1 second
try {
Thread.sleep(1000);
}
catch(Exception e) {}
seconds++;
System.out.println("Seconds: " + seconds);
//This needs to be looping the whole time.
//But right now, it's being blocked and only checked once
if(eventDetected() && seconds <= 2){
events++;
}
}
So you can see my problem. I can't split them up because then the second timer would run, and THEN eventDetected() would be checked. I need it to check constantly DURING the two second timer...so I basically need both things to happen at once. Is there any way I can do this?
Thanks for any help ahead of time!
I think your design pattern needs work -- I don't know what type event you're looking to detect, but no matter how short your sleep time is, there's a chance you could miss an event using the current pattern. Here's what I suggest:
Have eventDetected() increment your events counter. That way, you won't miss an event.
Then, you just need a way to turn on and off listening (and perhaps resetting the event counter). If you're sure that in you're current pattern you are really in a different thread that won't block your eventDetected() method, you could set a flag to check. For example:
When you want to start listening:
listenForEvents = true;
In eventDetected():
if (listenForEvents) { events++; }
When you want to stop listening (for example, after your Thread.sleep() call):
listenForEvents = false;
With multithreading, make sure to watch out for concurrency issues checking and setting the variables, of course.
I would tell you what kind of event I have to keep track of but then I'd have to kill you :D
Answered my own question. Hopefully this will help anyone else out who has a similar problem at some point! I looked up multithreading a bit...
I created a new class EventTimer which implements Runnable, with a public field for seconds:
public class EventTimer implements Runnable{
int seconds;
static int timerThreadCount = 0;
Thread t;
public EventTimer() {
timerThreadCount++;
this.seconds = 0;
t = new Thread(this, "Event Timer");
t.start(); // Start the thread
}
#Override
public void run() {
// TODO Auto-generated method stub
while(seconds < 2)
{
//Wait 1 second
try {
Thread.sleep(1000);
}
catch(Exception e) {
System.out.println("Waiting interupted.");
}
seconds++;
System.out.println("Seconds: " + seconds);
}
}
}
Then I used an instance of the EventTimer, and used a while loop & if statement to solve my problem.
EventTimer t = new EventTimer();
while(t.seconds < 2){
if(eventDetected()) events++;
}
It was actually quite simple! I realize that each iteration of my loop of operation (since the entire code piece above is inside an infinite loop) will create a new EventTimer thread and I will eventually run into memory problems however. How would I close/end a thread after the timer has reached 2 seconds?

Program not waiting for Timer to finish before continuing its loop

I have the following code that runs whenever you click the Start button on my program. I have denoted via comments where I want the timer to go, problem is, when I do thread.sleep(time) it freezes my program! So, I was wondering if someoen could just simply add atimer to my code so it runs the first bit, waits, then runs it again based on bumpNum.
Code:
public class startReplyButtonListener implements ActionListener{
public void actionPerformed(ActionEvent ev){
int length = textAreaReplyMessage.getText().length();
int remLen = 400 - length;
String strHTML = neo.get("http://www.neopets.com/neoboards/topic.phtml?topic=" + txtTopicID.getText());
/*strHTML = neo.post("/neoboards/process_topic.phtml?", new String[][] {{"boardType", "topic_id", "board_id", "message", "next", "remLen"}, {"reply", txtTopicID.getText(), "4", textAreaReplyMessage.getText() , "1", ((Integer)remLen).toString()}});
if(strHTML.contains("No topic with ID")){
txtLog.append("Invalid Topic ID! \n");
}
else{
txtLog.append("Bumped Topic ID " + txtTopicID.getText() + "\n");
}
*/
System.out.println(strHTML);
bumpNum = 5;
wait = Integer.parseInt(textWait1.getText()) * 1000; //converting to miliseconds
int i=1;
do{
strHTML = neo.post("/neoboards/process_topic.phtml?", new String[][] {{"boardType", "topic_id", "board_id", "message", "next", "remLen"}, {"reply", txtTopicID.getText(), "4", textAreaReplyMessage.getText() , "1", ((Integer)remLen).toString()}});
txtLog.append("Board Bumped. Waiting "+ ((Integer)(wait/1000)).toString() +" Seconds..." + "\n");
//ADD TIMER HERE
i++;
}while(i <= bumpNum);
}
}
What I wish to accomplish:
User indicates how many times they want to "post"(indicated by bumpNum), the loop will first, post once:
strHTML = neo.post("/neoboards/process_topic.phtml?", new String[][] {{"boardType", "topic_id", "board_id", "message", "next", "remLen"}, {"reply", txtTopicID.getText(), "4", textAreaReplyMessage.getText() , "1", ((Integer)remLen).toString()}});
Then:
Based on users input, it will wait for however many seconds(txtWait1) and THEN repeat the posting code above until it has reached bumpNum.
And it will update txtLog with the following EACH TIME it bumps(so the program cannot be frozen):
txtLog.append("Board Bumped. Waiting "+ ((Integer)(wait/1000)).toString() +" Seconds..." + "\n");
Edit:
Sigh. Ok, now I understand. I don't know the answer. You are talking about drawing a GUI element. I suspect you want to fork a thread to do a job and then show the GUI display that you are waiting for it. You need to wait for the thread to finish (see my join code below) all of the time having the GUI element refresh UNTIL it finishes when you display some result.
This depends more on the GUI code than sleep/timer. I would start a new question now and explain !!!NOT WITH CODE!!! but with pseudo code from 1000 foot view what you want. Something like:
I am trying to fork a thread that runs in the background in [Swing/Android/etc]. I want to display to the user that the thread has been forked, I want the user interface to wait for the thread without freezing, and then I want the user interface to join with the thread and display the results.
Think about the problem like we have to think of it. Anticipate questions that we will ask. Figure out what we don't and can't know about your environment.
Best of luck.
Edit:
If you are just trying to call sleep then you don't need to fork a thread for that. All you need to do in your code is:
try {
Thread.sleep(waitingTime);
System.out.println(waitingTime);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
e.printStackTrace();
}
This will pause the current thread (which could be the main thread) for waitingTime milliseconds.
So you are forking 3 threads very quickly which I guess you don't want to do. If you are trying to wait for each thread to finish then you will have to do something like:
Thread thread = new Thread(new Counter(wait));
thread.start();
thread.join();
Couple of other comments:
It is considered bad form to start a thread in the constructor of a class: new Thread(this).start();
You are creating 2 thread objects inside of your Runnable. You should just create one outside of your Runnable. See above.
Thread myCounter = new Thread(this); << #1
public Counter(int waitingTime) {
new Thread(this).start(); << #2
}
I would not initialize waitingTime = 0; when defined and initialize it in the constructor. This is confusing. Remove the = 0.
    int waitingTime; << remove the =0 here
    public Counter(int waitingTime) {
 this.waitingTime = waitingTime;
When you catch InterruptedException, be sure to handle it right. A good pattern is to reset the interrupt flag and/or quit the thread:
} catch (InterruptedException e) {
// resets the interrupt flag cleared by catching the exception
Thread.currentThread.interrupt();
// or stops the thread immediately
return;
}
You're starting a new thread each time through the loop. Rather than creating a new thread in the constructor, move the do/while loop into a normal method rather than the run method of a new thread. What you're doing is spawning a new thread that does in fact sleep, but it's not the thread that's executing the loop so that thread just continues as normal.

Categories

Resources