Pause loop on user input - java

If I have a loop like this:
for(int i = 0; i <= 10; i++) {
System.out.println("Hello, User " + i;
Thread.sleep(1000)
}
How would I go about adding code that did not require user input, but if the user chose the pause the loop at a given point, they could do so, and resume a few moments later?

For this , you'll need to implement multi-threading. One thread will run the loop(T1) while other can wait for the user input(T2).
T1 - while --> check if input through common bool attribute -->
continue/break loop
T2 - wait for input --> if input=="pause" --> set common attribute to true to
pause loop
Something like :
class MultiThread implements Runnable {
boolean gotInput = false;
int i = 0;
public void run() {
for(;i <= 10 && !gotInput; i++) {
System.out.println("Hello, User " + i;
Thread.sleep(1000)
}
}
public static void main(String args[]) {
MultiThread mt = new MultiThread ();
Thread t = new Thread(mt);
t.start();
Scanner s = new Scanner(System.in);
while (!s.next().equals("pause"));
test.gotInput = true;
}
}
On the same lines you can resume the code if needed.

Try creating a background thread that waits 1 second for the user to select pause. If it is not selected within that 1 second, move forward.
The way this is written, your Thread.sleep() will lock up the UI for 1 second, and regardless of what the user does it won't affect your program.

Related

Guessing Number within Time Limit [Threads]

I've been practicing with threads, so I wrote up this timed game where the user needs to guess the correct number (ranges from 1-10). If the user guesses the correct answer in the time limit, the thread stops and the program terminates. It fails to work when the user fails to guess within the time limit. Even though it enters the if-statement after the time limit, it still fails to interrupt the thread completely unless I guess the correct number. I have read other threads but they seem to use ask about the "traditional" guessing game or utilizing Timer. Explanation and/or tips for a suggested solution is also appreciated.
import java.util.*;
import static java.lang.System.out;
import java.io.*;
public class Threading implements Runnable {
private static int num;
private static int k;
public void run() {
try {
Scanner line = new Scanner(System.in);
k = -1;
out.println("Guess!");
while (k != num) {
k = line.nextInt();
if (k != num) {
out.println("Nope");
}
}
}
catch (Exception e) {
out.println("I'm not done!");
}
}
public static void main(String args[]) throws InterruptedException {
num = (int) (Math.random() * 9 + 1);
out.println(num);
Thread t = new Thread(new Threading());
t.start();
long patience = 1000 * 5;
long startTime = System.currentTimeMillis();
while (t.isAlive()) {
t.join(1000);
if (((System.currentTimeMillis() - startTime) > patience) && t.isAlive()) {
out.println("I'm in here!");
t.interrupt();
t.join();
out.println("Times up!");
}
}
}
}
Since one of the comments already points out that the call to nextInt will block I don't think there is a need to go into the details of that.
So for now I'm going to assume you're fine with allowing the user 1 final guess after the timer expires.
The following is the modified code including my comments. I refer to the thread you named t as the "guessing thread".
private static int num;
private static int k;
//Changed variable "line" to "scanner" and made it static so that the
// main method can close it once everything is done.
private static Scanner scanner = new Scanner(System.in);
public void run() {
try {
k = -1;
System.out.println("Guess!");
while (k!=num) {
//Added a check for interrupt, otherwise this thread will never
// end unless the user enters the correct answer.
if(Thread.currentThread().isInterrupted())
return;
k = scanner.nextInt();
if(k != num){
System.out.println("Nope");
}
}
System.out.println("Correct!");
} catch (Exception e) {
System.out.println("I'm not done!");
}
}
public static void main(String args[]) throws InterruptedException {
num = (int) (Math.random() * 9 + 1);
System.out.println(num);
//Declared the guessing thread as final so it can be used inside of
// the TimerTask that is created later.
final Thread t = new Thread(new GuessUntilTimeLimit());
t.start();
long patience = 1000 * 5;
//Use a Timer to enforce your time limit, the TimerTask will execute
// an interrupt of your guessing thread if the thread is still alive
// (it may have died already if user got right answer)
Timer timer = new Timer();
TimerTask task = new TimerTask(){
#Override
public void run() {
if(t.isAlive()){
t.interrupt();
System.out.println("Times up! Enter your final guess now.");
}
}
};
timer.schedule(task, patience);
//Wait for the guessing thread to finish before canceling the timer
t.join();
//By now either the user got the answer or time has run out. Either way
// we need to clean up by canceling the timer.
timer.cancel();
//Added a call to close the scanner, it's always important to release
// resources
scanner.close();
}
Now your main thread schedules a task to execute after patience milliseconds. This task is then responsible for interrupting the "guessing thread". The "guessing thread" will check for interrupt and stop itself when appropriate.
Again, depending on your requirements, you may need to alter the way you accept user input since nextInt will block the thread. For completeness I'm including a link to the question regarding interrupting Scanner.nextLine mentioned in the comments.

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 ;)

Can a while loop wait for an event to continue java

I have a hangman engine that uses a JOptionPane to get the users guess, but now that I am implementing a GUI with a text field, I need a way to stop the engine and get the users guess from the text field - I'm trying to use MVC so at the moment the data from the text field gets sent to the main/controller class however after the data is loaded into a variable in the main class - I start having trouble integrating that data into the engine
I don't know if adding a wait to the engine would be the best thing but that's all I can really think of.
Here is my engine class:
public class engine {
char [] charda = new char[20];
char [] charwo = new char[20];
Highscore words = new Highscore();
main mn = new main();
int guesses =7;
char guess;
public engine() {
}
public void enginer(){
int count = 0;
String word = words.getWord();
for (int i = 0; i<word.length(); i++)
{
//instantiates two arrays one of dahses and one with the word
charwo[count] = word.charAt(i);
charda[count]= '_';
count++;
}
for (int l=0; l<count; l++)
{
System.out.print(" "+charda[l]);
}
while (guesses != 0 && !Arrays.equals(charwo, charda))
{
System.out.println("");
guess = JOptionPane.showInputDialog("enter a Guess").charAt(0);
if (word.toUpperCase().contains(String.valueOf(guess).toUpperCase()))
{
for (int k = 0; k<word.length(); k++)
{
if (String.valueOf(guess)
.toUpperCase()
.equals( String.valueOf(charwo[k]).toUpperCase() ))
{
charda[k]=charwo[k];
for(int l=0; l<count; l++)
{ // prints dashes here to avoid a letter being
// chopped off by the program stopping in the middle
System.out.print(" "+charda[l]);
}
}
}
}
else
{
guesses = guesses-1;
System.out.println("guesses left "+guesses);
//
//Re-displays dashes
for (int l=0; l<count; l++)
{
System.out.print(" "+charda[l]);
}
}
if (Arrays.equals(charwo, charda))
{
System.out.println("");
System.out.println("You are Winner");
}
}
}
}
Here is the part of my main class that handles the button click
public void buttonClicked ()
{
gameplay gp = new gameplay();
engine en = new engine();
en.guess = gp.getInput; // this is where I try send the input from the text field to the engine
en.enginer();
System.out.println("button clicked");
}
I'm really lost at the moment so even a nod in the right direction would be really helpful :)
Generally waiting can be implemented using wait/notify built-in java mechanism.
Although you can find a bunch of tutorials that explain this issue here is a very brief explanation.
Each class in java automatically extends java.lang.Object that defines methods wait() and notify(). Wait suspends current thread until notify() is called on the same object. The object that is used to invoke wait() and notify() is called monitor. Following rules of java thread management both method must be invoked from synchronized block, i.e.
synchronized(obj) {
obj.wait();
}
Now the answer to your question is simple. Define monitor object that is visible from both points (I mean code that should wait and code that should trigger the first thread to continue).
Implement waiting as:
synchronized(obj) {
obj.wait();
}
When use clicks button (so you want the wait to exit) you should invoke code:
synchronized(obj) {
obj.notify();
}
That's it. Pay attention that there is version of wait with timeout and there is notifyAll() too. And IMHO take some time to learn java threads, synchronization etc. It is fun. Good luck.

Does Java SWT Widgets influence Thread perfomance?

I'm using StyledText 400x100 widget and it's working like a console where the program interacts with the user.
This is how I update the widget:
private static Shell MainShell = null;
public void createPartControl(Composite parent){
MainShell = parent.getShell();
}
public static void updateConsole(final String newMessage){
if(MainShell.isDisposed() || myStyledText.isDisposed() ) return;
MainShell.getDisplay().syncExec(new Runnable(){
myStyledText.setText( newMessage + "\n" + myStyledText.getText() );
});
}
Similar to append(), but this one insert to the first line and inserts a line break "\n".
I'm using CycleBarrier to handle Threads. Currently it's running 300+ threads, and I'm allowing only 10 threads / cycle to not kill the CPU.
// divide 300/10 because there is an inner for() which runs 10 threads / cycle
for(int n = 0; n < 300/10; n++){
// allow only 10 threads to work
final CycleBarrier br = new CycleBarrier(10);
for(int i = 0; i < 10; i++){
new Thread(new MyClass(cb).start();
}
//waiting for Threads to reach the barrier
br.await();
}
And now the MyClass class:
public MyClass implements Runnable{
private CycleBarrier cb;
public MyClass(CycleBarrier cb){
this.cb = cb;
}
#Override
public void run(){
for(int i = 0; i < 256; i++){
for(int j = 0; j < 256; j++){
//View is the main class (eclipse RCP) and updateing the widget
View.updateConsole("matrix["+i+"]["+j+"]");
// Just an integer which counts the number of the loops
View.TOTAL_LOOPS++;
}
}
cb.await();
}
}
This was an example. It should write to the View widget in asynchronous ways (not in order) because the Threads doesn't reaches the barrier in order.
I'm using eclipse RCP (3.8).
ISSUE
Why the program is working correct in DEBUG mode? I have set a breakpoint where I'm starting new Threads (in the inner for() ) and I'm clicking the Resume button to start threads one by one.
When I'm trying to open in normal mode (RUN or exported) there are "leaks" (I don't know how to name), there are less lines in the console.
View.TOTAL_LOOPS
Should have in total:
256*256*10*30 = 19660800 // View.TOTAL_LOOPS++; in the MyClass
and in normal run it's having dynamic results: 174614904, 17025759, etc. In DEBUG mode it's reaching the exact value.
Question:
Are the Threads being killed?
It has nothing to do with SWT. You are incrementing a single shared variable from 10 threads at once. This is a classic example of a race condition. Since ++ isn't an atomic operation, something like this can happen:
int temp = View.TOTAL_LOOPS; // in thread 1
int temp = View.TOTAL_LOOPS; // in thread 2
int temp2 = temp + 1; // in thread 1
View.TOTAL_LOOPS = temp2; // in thread 1
int temp2 = temp + 1; // in thread 2
View.TOTAL_LOOPS = temp2; // in thread 2
Note View.TOTAL_LOOPS only increases by 1 after this, and obviously it won't happen if you start threads one-by-one.
Use an AtomicInteger instead if you just want a thread-safe counter or otherwise synchronize your threads properly.

Java Thread Yielding/ Starvation Problem

I'm writing a code that will run a multithreaded bank. I first create an array of threads with one program, then pass them into another thread that runs a loop to start them. For part of the application, I have a CPU intensive method that basically runs a series of loops within one another. Only problem is, for some reason it is not yielding the way that I think it should. Here is the code that is running the threads:
public void run(){
this.setPriority(MAX_PRIORITY);
int count = 0;
while(count<transactions.length){
int copy = count;
if(transactions[copy] instanceof Jumbler){
System.out.println(copy + " is a jumbler.");
}
else{
System.out.println(copy + " is not a jumbler");
}
transactions[copy].run();
count++;
}
}
Then here is the Jumbler run method:
public void run(){
System.out.println("running jumbler");
Thread.yield();
Thread.currentThread().yield();
try{
Thread.currentThread().sleep(5000);
}catch(InterruptedException e){}
//this.setPriority(MIN_PRIORITY);
System.out.println("still running.");
Thread.yield();
nums = new int[1000];
int i = 0;
do{
Thread.yield();
for(int x=0;x<1000;x++){
Thread.yield();
//System.out.println("in the loop");
nums[x]=(int)(Math.random()*10000)+1;
for(int y = 0;y<1000;y++){
Thread.yield();
//System.out.println("in the the loop");
for(int z = 0;z<100;z++){
Thread.yield();
}
}
}
Thread.yield();
i++;
System.out.println(whichJumble + ": " + i);
}while(i<1000);
}
So, the problem is that I want it to yield, allowing the main method to continue running more threads, but it blocks and waits for the Jumbler to complete (which takes a long time). Any idea why that would happen or how to fix it?
I suppose the issue comes with transactions[copy].run(); in your main loop. This one calls the run method directly but not in another system thread. Instead start the thread with transactions[copy].start();.
It seems that you're spawning the thread correctly (in fact, you're not spawning them at all)
If you want a Thread to start running (concurrently to the current thread) you need to call the start() method of that Thread object, which you don't.
If I understand your code correctly, you want the first snippet to spawn the other threads. Therefore you should change transactions[copy].run() to transactions[copy].start().
(This an educated guess. It would be nice if you showed the definition of the transaction array.)
Here's the typical scheme of launching several Threads:
class MyThread extends Thread {
public void run() {
// Do something here ...
}
}
// Prepare the array
MyThread[] arr = new MyThread[10];
for(int i = 0; i < arr.length; ++i)
arr[i] = new MyThread();
...
// Launch the threads
for(int i = 0; i < arr.length; ++i)
arr[i].start();
Once the thread is running, i don't think you can be guaranteed that priority changes when you call setPriority.
these two statements do the same thing:
Thread.yield();
Thread.currentThread().yield();
but you probably shouldn't be calling yield, let the os do that.

Categories

Resources