Blocking method in Thread - java

I'm trying to develop a timer for chess game.
There should be a function like
wait for user input there move from Console
if wait time > 60
stop waiting and keep going.
What I can think of to solve this is using Thread like:
public class Game {
Thread t1 = new PlayDisc(this);
Thread t2 = new Timer(this);
public static void main(String[] args) {
t1.start();
t2.start();
}
}
public class Timer extends Thread{
Game g;
public Timer(Game g) {
this.g = g;
}
#Override
public void run() {
int i = 0;
while(true){
if(i > 6000) {
g.t1.interrupt();
break;
}
}
}
}
public class PlayDisc extends Thread{
private Game g;
public PlayDisc(Game g) {
this.g = g;
}
#Override
public void run() {
Scanner s = new Scanner(System.in);
int x = s.nextInt();
int y = s.nextInt();
Point p = new Point(x, y);
cm.nextPoint = p;
s.close();
}
}
I know this will not work as Scanner.nextInt() is a blocking method. But I'm required to read input from cmd line.
Is there any way to solve this?

There is already a Timer class (in fact two of them, java.util.Timer and javax.swing.Timer). But as you've realized, the blocking nature of nextInt() prevents you from doing anything after the timeout. You would need an additional library that would give you better console control than Java does by default. That, or use Swing.
Edit: It might be possible to perform a hack of some sorts, by using a polling loop with hasNextInt(). That way you wouldn't let the scanning thread block.
Re-Edit: Nah, it's not possible, since hasNext() will block. You'll have to test whether the interrupt will get you out of the trouble here (it might not).

The problem with Scanner is that you don’t have control over the method’s reading more bytes which can always cause blocking. The safe way is to read from System.in manually and create a Scanner which can only read the bytes you already got from the console. Then you can do polling (with sleeping) for implementing a time-out. By choosing the right amount of time for sleeping you get the right balance between responsiveness and CPU usage.
The example program below uses a check interval of 200ms which is good enough to be perceived as “immediate response” by a human user. This value is independent from the wait time which you can configure freely (as long as it is significantly higher than the check interval).
Other things to be aware of is that we calculate a deadline at the beginning rather than aggregating waiting times to be independent of CPU usage within the loop. And we use System.nanoTime() to be independent from changes that might happen to the system’s clock.
long timeOutNS=TimeUnit.MINUTES.toNanos(1); // 1 min timeout
long checkNS=TimeUnit.MILLISECONDS.toNanos(200); // check input every 200ms
int input=0;
boolean hasInput=false;
readWithTimeOut: {
System.out.println("Enter int: ");
long deadLine=System.nanoTime() + timeOutNS;
for(;;) {
int a = System.in.available();
if(a>0) {
byte[] b=new byte[a];
a=System.in.read(b);
if(a<=0) break readWithTimeOut;
Scanner scanner=new Scanner(new ByteArrayInputStream(b, 0, a));
if(scanner.hasNextInt()) {
input=scanner.nextInt();
hasInput=true;
break;
}
else if(scanner.hasNext())
System.err.println("not an int: "+scanner.next()); // consumes token
continue;
}
long remaining=deadLine-System.nanoTime();
if(remaining<=0) {
System.err.println("timeout");
break readWithTimeOut;
}
LockSupport.parkNanos(Math.min(remaining, checkNS));
}
}
System.out.println( hasInput? "entered "+input: "no valid input" );

InputStream.available() is a non-blocking method that you can use to check if there's something in the stream.
If you don't care about spinning (and thus wasting a processor core) that's as simple as it can get:
import java.io.IOException;
import java.util.Scanner;
public class ConsoleReadWithTimeout {
static Scanner scanner = new Scanner(System.in);
public static void main(String[] args) throws Exception {
int i = readIntWithTimeout(5 * 1000);
scanner.close();
}
// returns -1 in case of timeout
static private int readIntWithTimeout(long timeoutInMs) throws IOException {
long startTime = System.currentTimeMillis();
while (System.in.available() == 0) {
if (timeoutInMs < System.currentTimeMillis() - startTime) {
return -1; // or maybe throw a TimeoutException ?
}
}
return scanner.nextInt();
}
}

Related

Java Thread Creates extra Threads for unclear reasons

Java Thread Creates extra Threads I'm not sure why this happens! I'm still a noob at java if its very obvious I'm sorry but please help me out
Well I created 2 threads to do something but there are extra threads created
here's the code
import java.util.*;
import java.util.Arrays;
class consuming_producing extends Thread {
static int arrX[] = new int[300];
int y;
static int var=0;
int Request_type;
consuming_producing(int x, int Request) {
y = x;
Request_type = Request;
}
int thread_number;
consuming_producing(int x, int Request ,int thread) {
y = x;
thread_number=thread;
Request_type = Request;
}
public synchronized void run() {
switch (Request_type) {
case 1: {
// start producing the data and store it to the array
for (int i = y; i < 300; i = i + 3) {
arrX[i] = (int) (Math.random() * 10 + 1);
System.out.println("produced " + arrX[i]);
}
}
// *******************
case 2: { // consuming the data
for (int ww = y; ww < y+150;ww++) {
int sum = Arrays.stream(arrX).sum();
System.out.println("Sum =" +var+" by thread " + thread_number);
//Arrays.fill(arrX,0);
var+=1;
}
}
}
}
}
class consumer_producer {
public static void main(String[] args){
consuming_producing arr_Producer_obj[] = new consuming_producing[3];
// create a [enter image description here][1]thread for producing
for (int i=0;i<3;i++){
int x =0;
arr_Producer_obj[i]=new consuming_producing(x,1);
arr_Producer_obj[i].start();
x+=1;
}
// ***************
consuming_producing arr_Consumer_obj[]=new consuming_producing[2];
int thread=1; // this is the name of thread im creating for ny refrence
int x=0;
for (int i=0;i<=1;i++){
arr_Consumer_obj[i]=new consuming_producing(x,2, thread);
arr_Consumer_obj[i].start();
x+=150;
thread+=1;**
}
}
}
here's the image of output please check this
each time your program reaches a Thread.start() method, its creating a new thread, plus the base thread of the main() method/entry point.
Your main method has 2 for loops, the first looks like it would create 3 threads, and the 2nd looks like it would create 2 additional threads.
When you extend the Thread class, and implement the 'run()' method, calling start() on the instance of the class will create a new thread to run the 'run()' method on.
Well, your code has a lot of problems. But answer to your questions is simple:
You create a bunch of threads in 2 for loops, but there is no points of synchronization\ communication between threads, so they act independently in the meaning that when you call start method of a Thread instance it will execute run method, well, in separate thread. There is nothing in you program that prevents threads if 2nd loop to be created only after threads from 1st loop finish their execution. So there are no extra threads created here. You just solve your solution in a wrong way.

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

Text based game with a separate timer loop?

I have started a Java coding short course at a university about 5 months ago. I have learnt quite the amount of things with regards to Java coding, but am still lacking in other things such as threads, handling exceptions, or even making JFrame games. I decided to embark on a text based game to just learn and figure out how a game loop should work (kind of), and how the logic should work (still, very "kind of"). The game I wrote runs with if-else commands, thus you get displayed a screen, type in the command of the option you want to pick, and it bumps you to the next menu, very standard of course. I run these if-else statements within nested for loops.
My nested for loops looks like the following:
// This is just an example, they're actually a lot more cluttered
// in my actual source code.
mainMenu.writeOutput();
reply = keyboardInput.nextLine();
for (int i = 0; i <= 10; i--)
{
for (int ii = 0; i <= 10; i--)
{
if (reply.equalsIgnoreCase("/help")
{
System.out.println("Here I have a separate call to a class
file (excuse me, forgot the exact wording), thus it
call something like help.writeOutput(); to display
the help menu");
reply = keyboardInput.nextLine();
if (reply.equalsIgnoreCase("/makegameeasy")
{
// Just an example.
gamedifficultyEasy.writeOutput();
reply = keyboardInput.nextLine();
if (reply.equalsIgnoreCase("/back")
{
mainMenu.writeOutput();
reply = keyboardInput.nextLine();
break;
}
}
else if (reply.equalsIgnoreCase("/makegamedifficult")
{
// Another example.
gamedifficultHard.writeOutput();
reply = keyboardInput.nextLine();
if (reply.equalsIgnoreCase("/back")
{
mainMenu.writeOutput();
reply = keyboardInput.nextLine();
break;
}
}
else if (reply.equalsIgnoreCase("/back")
{
mainMenu.writeOutput();
reply = keyboardInput.nextLine();
break;
}
}
else
{
System.out.println("Here I print out an error for incorrect
input received, standard fare.");
mainMenu.writeOutput();
reply = keyboard.nextLine();
break;
}
}
}
As mentioned, the above is just an example, it's not very elegant, and I can probably use Exceptions for any incorrect info submitted by the user, however I do not know too much of Exceptions to comfortably add them, so I'll do that at a later time, however my main issue at the moment is a part of my game where "resource mining" has to be done on regular intervals. I have been all over Google, but still can't quite catch how to set a Thread or Timer up for my game so it does the mining automatically, and the player can go on with their game.
The game is essentially one of those games where you build up a base, upgrade your mining tools, and generate more "stuff". I have pasted a few blocks of code from my "mining" class file below that will basically run how much of one thing should be mined. In the game you will be able to buy upgrades of course, so it will get factored into your mining speed.
// I initiate my variables a lot earlier, but just for some
// clarity, I have initiated the variables in the below methods,
// they will not work correctly anyway, I am aware of that, however
// I didn't want to add the other "get, set and initiate"
// variables and methods everywhere, as to not spam this block of code.
// upgradeOS, upgradeHF, and upgradeLM all have their own respective
// set and get methods. They are also all int variables.
public void handleOS()
{
// OS = short for Oxygen Silo
int mineOS = os.getStoredO2() + (1 * upgradeOS);
os.setStoredO2(mineOS);
}
public void handleHF()
{
// HF = short for Hydrogen Fuel
int mineHF = hf.getStoredO2() + (1 * upgradeHF);
hf.setStoredO2(mineHF);
}
public void handleLM()
{
// LM = short for Liquid Minerals
int mineLM = lm.getStoredMinerals() + (1 * upgradeLM);
lm.setStoredMinerals(mineLM);
}
// This is what's going to run the whole time on the set intervals.
public void mine()
{
mineOS = os.getStoredO2() + (1 * upgradeOS);
mineHF = hf.getStoredO2() + (1 * upgradeHF);
mineLM = lm.getStoredMinerals() + (1 * upgradeLM);
os.setStoredO2(mineOS);
hf.setStoredO2(mineHF);
lm.setStoredMinerals(mineLM);
}
// Using 10 seconds here to have it update as quickly as possible so I can
// see any changes. This is just here to write an output.
public void getUpgradeInfo()
{
System.out.println("Oxygen: " + (1 * upgradeOS) + " / per 10 seconds.");
System.out.println("Hydrogen: " + (1 * upgradeHF) + " / per 10 seconds.");
System.out.println("Liquid Mineral: " + (1 * upgradeLM) + " / per 10 seconds.");
}
I'm not the best naming schemes for my materials...
TL;DR: I can't figure out how to implement a thread or timer just for the above mentioned mine() method since I do not have the appropriate amount of knowledge. My if-else rules aren't too elegant, but I'll work on those of course. Basically the if-else rules should run separately from the mine() method, and you can do some AFKing without the game updating the System.out output, thus you can be floating in, for example, the Oxygen Silo upgrade menu, and you won't be bounced back to a different menu due to a thread "waking up", such as being bounced to the main menu, but the mine() method will still generate resources in the background as it should.
Any help on this, or just even a nudge in the right direction will be greatly appreciated.
To answer the question you asked, you can do something like this:
import java.util.*;
TimerTask tt = new TimerTask() {
public void run() {
mine();
}
}
Timer t = new Timer();
t.scheduleAtFixedRate(tt, 0, 1000);
Alternatively, you can use an ActionListener and the swing timer in a similar way. This has the advantage of being Thread-safe in case you build a swing gui on top
Lastly, you should check out the usage of synchronized and volatile to make sure that the variable(s) that are updated in mine() are done so in a thread-safe way
Thanks to #ControlAltDel, definite shove in the right direction. I have taken a bit of code and set it up like this:
import java.util.*;
// extends TimerTask needed
public class TimerTestOne extends TimerTask
{
// Needed
#Override
public void run()
{
TimerTestTwo ttt = new TimerTestTwo();
mine();
}
// Needed, method doesn't need the same name though.
private void completeTask()
{
try
{
//assuming it takes 10 secs to complete the task
Thread.sleep(10000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
public static void main(String[] args)
{
// You will need to define the following line of code:
TimerTask tt = new TimerTestOne();
Scanner keyboard = new Scanner(System.in);
String reply;
// Following 2 lines of code, yup, need them.
Timer timer = new Timer(true);
timer.scheduleAtFixedRate(tt, 0, 10*1000);
previousMenu();
for (int i = 0; i <= 10000; i++)
{
for (int ii = 0; ii <= 10000; i++)
{
System.out.println("Go to another menu?");
reply = keyboard.nextLine();
if (reply.equalsIgnoreCase("/yes"))
{
yes();
reply = keyboard.nextLine();
}
}
}
}
// I added the following methods, just so I didn't have to work
// off 2 class files.
public void mine()
{
System.out.println("Mined");
}
public static void yes()
{
System.out.println("Next menu");
}
public static void previousMenu()
{
System.out.println("Previous menu");
}
}
So there, if anyone ever needs to have a look at setting a timer up that won't break your text based game.

Pause loop on user input

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.

Categories

Resources