Hi guys, I'm new to Java and I'm takin a course at Uni. I have gotten a task to write a small game that generates a random nr that the player will guess. After guessing the player is supposed to get the option to play again or WAIT and automatically come back to the main menu.
First I tried thread.sleep(5000) but it got stuck because it was waiting for user input (nextLine). Then a friend told be about timer and timertask, which i used and now my game is almost working.
The only problem is when i call a new method from my run() method the old (play again Y/N) thread running in the background is not ended. So when my menu appears after 5 seconds, my first input is connected to the play again Y/N choice and not the main menu options. Here are the kod parts:
public void tryAgain() {
Timer timer = new Timer();
Task timerTask = new Task();
int y = 1;
String yesNo = sc.nextLine();
System.out.println("Try again Y/N");
Statistics.setGames(games);
timer.schedule(timerTask, 5000);
do {
try {
yesNo = sc.nextLine();
if (yesNo.equals("Y") || yesNo.equals("y")) {
guesses = 0;
y = 2;
timerTask.cancel();
playGame();
} else if (yesNo.equals("N") || yesNo.equals("n")) {
y = 3;
timerTask.cancel();
Statistics.setGames(games);
menu.showMainMenu();
} else {
System.out.println("Wrong input, try Y or N:");
}
} catch (Exception e) {
sc.next();
System.out.println("Wrong input, try Y or N:");
}
} while (y == 1);
}
and :
import java.util.TimerTask;
class Task extends TimerTask {
play menu = new play();
public void run() {
Statistics.getGames();
menu.menu.showMainMenu();
cancel();
}
}
You cannot interrupt blocking reads. But you can use the BufferedReader.ready() method, which will tell us whether the underlying stream is ready to be read.
Let's implement a non blocking reader:
public class OurNonBlockingConsoleReader implements Callable<String> {
public String call() throws IOException {
BufferedReader sysInReader = new BufferedReader(new InputStreamReader(System.in));
String answer;
do {
System.out.println("Try again Y/N");
try {
while (!sysInReader.ready()) {
Thread.sleep(100);
}
answer = sysInReader.readLine();
} catch (InterruptedException e) {
return null;
}
} while (!"y".equalsIgnoreCase(answer) && !"n".equalsIgnoreCase(answer));
return answer;
}
}
Next, we call this reader with a timeout, using the ExecutorService and the Future from java.util.concurrent package:
public void tryAgain() throws InterruptedException, ExecutionException {
ExecutorService readerExecutor = Executors.newSingleThreadExecutor();
Future<String> readerResult = readerExecutor.submit(new OurNonBlockingConsoleReader());
try {
String answer = readerResult.get(5, TimeUnit.SECONDS);
if ("y".equalsIgnoreCase(answer)) {
playTheGame();
} else {
goToMainTheMenu();
}
} catch (TimeoutException e) {
goToMainTheMenu();
} finally {
readerExecutor.shutdownNow();
}
}
The readerResult.get(...) call will wait 5 seconds for a valid answer. It there is no valid answer returned from OurNonBlockingConsoleReader.call, the Future.get will raise a TimeoutException.
Addressing only your immediate problem:
Your run method needs to set y to something other than 1 (perhaps 0), then call interrupt on Y/N thread. This will kick it out of a blocking read with an InterruptException or ClosedByInterruptException. (Your catch block will need to be smarter.) Then the Y/N loop will finish because y is not 1. End of problem.
For this to work, y needs to be declared volatile, or each thread might use its own copy. (Accessing it only within synchronized blocks will work also.)
Added Example:
public class YesNo {
private volatile Thread tryAgainThread;
private volatile int y = 1;
public doNotTryAgain() {
y = 0;
tryAgainThread.interrupt();
}
// Called only from tryAgainThread thread.
public void tryAgain() {
do {
try {
// Exactly what you have now.
...
}
catch (Exception e) {}
} while (y == 1);
}
....
class Task extends TimerTask {
public YesNo ynInstance;
...
public void run() {
ynInstance.doNotTryAgain();
Statistics.getGames();
...
}
}
I'll let you figure out how to set tryAgainThread, which is the thread the tryAgain method is called--and is looping--on. Also, Task needs to know the relevant (and probably only) instance of the class that contains the tryAgain call running in the 'tryAgainThread'. In your case some static public fields will do the job, but ideally you'd want something more elegant.
Also, catch (Exception e) {} will work fine, but ideally you'd check your exceptions better.
Related
why my thread can't be stopped???
class Threadz {
class runP implements Runnable {
int num;
private volatile boolean exit = false;
Thread t;
public runP() {
t = new Thread(this, "T1");
t.start();
}
#Override
public void run() {
while(!exit) {
System.out.println(t.currentThread().getName()+": "+num);
num++;
try {
t.sleep(200);
} catch(InterruptedException e) {}
}
}
public void stop() {
exit = true;
}
}
public static void main(String[] a) {
runP rp = new Threadz().new runP();
if(rp.num == 1) {rp.stop();}
}
}
if i use rp.num == 0, the thread can be stopped immediately. But, why when i changed the rp.num == x (x is any number greater than 0) the thread cannot stop? please help me solve this thing... thanks for any helps.
Because this code is not executed in the run() method of the thread :
runP rp = new Threadz().new runP();
if (rp.num == 1) {
rp.stop();
}
It works with 0 as the default value of int is 0.
But it is not necessarily true in all executions of the application as the thread of runP could run and incrementnum before the check : if (rp.num == 0)
Move the stop condition in the run method of the runP thread :
#Override
public void run() {
while(!exit) {
System.out.println(t.currentThread().getName()+": "+num);
num++;
try {
t.sleep(200);
} catch(InterruptedException e) {}
if (rp.num == 1) {
exit = true;
}
}
}
I'm sure if you run the program many many times, It'll be a case when the program actually stops.
The reason is at the time you run the program there is much more chance of executing
if(rp.num == 1) {rp.stop();}
before num++ in your run() method changes value.
However by chance you may come across a case that the loop in your run method gets executed before that if statement in your main method.
one way to make sure this happens is to continuously checking for the condition:
e.g.
public static void main(String[] a) {
runP rp = new Threadz().new runP();
while(true){
if(rp.num == 1) {
rp.stop();
break;
}
}
}
Statement below is getting executed before the thread starts executing the run method.
if(rp.num == 1) {rp.stop();}
Add Thread.sleep before the above statement, it works fine as it will execute this statement after starting the loop.
public static void main(String[] a) {
runP rp = new Threadz().new runP();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(rp.num > 1) {rp.stop();}
}
I have made it >1 to test.
Checking rp.num == 1 would have to happen exactly at a point where rp.num is exactly one, which is rather unlikely.
In your main method, you start a thread which increments num every 200 ms. Afterwards, you check if num == 1, but when exactly this code is executed depends on a lot of factors you cannot really control (scheduling of the OS, etc...). This might be after 10 ms (where the value would be 1), but could also be after 300 ms (when the value is already 2). Also when the thread is exactly started is unsure. Therefore it is also possible that your thread only starts after the test. You can easily test this by replacing the check if(rp.num == 1) {rp.stop()}; with a simple print statement System.out.println(rp.num). If you additionally wait for some time before printing, you might get a better feeling of what I am talking about.
Supposing you would like to stop a runnable from outside, I suggest to use something like the Observer pattern:
class MyRunnable implements Runnable {
private final MyListener l;
private volatile boolean exit;
int num;
public MyRunnable(MyListener l) {
this.l = l;
exit = false;
}
#Override
public void run() {
while(!exit) {
System.out.println(t.currentThread().getName()+": "+num);
l.check(num++);
try {
t.sleep(200);
} catch(InterruptedException e) {}
}
}
public void stop() {
exit = true;
}
}
class MyListener {
private final threshold;
public MyListener(int x) {
this.threshold = x;
}
public void check(MyRunnable r, int num) {
if (num >= threshold)
r.stop();
}
}
and your main method would look something like
public static void main(String[] args) {
MyListener l = new MyListener(1);
Runnable r = new MyRunnable(l);
new Thread(r).start();
}
This question already has answers here:
Should you synchronize the run method? Why or why not?
(6 answers)
Closed 7 years ago.
I need to create 2 classes, Class Player and Class Referee which implement Runnable interface(Basically, create threads).
The order in which the threads have to be executed are
Referee
Player 1 or 2
Referee
Player 1 or 2
and so on..
Here, is the solution that I came up with, but, the order doesn't seem to happen. Players keep playing even before referee completes checking.
``
public class a {
public static synchronized void main(String[] args) throws InterruptedException {
ready = false;
finish = false;
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.execute(new Referee());
executorService.execute(new Player(1));
executorService.execute(new Player(2));
Thread.sleep(1000);
executorService.shutdown();
executorService.awaitTermination(1, TimeUnit.MINUTES);
}
/*....FOLLOWED BY GETTER AND SETTER METHODS
*
*
*/
}
class Player implements Runnable{
public synchronized void play() throws InterruptedException{
//continue playing unless game is over
while(true)
{
while( (a.getReady()) != true){
wait();
}
/***
*
*
*
execute some code to play
**/
//Change the value of the condition variable for the referee to start executing
a.putReady(false);
}
}
#Override
public void run() {
try {
play();
} catch (InterruptedException ex) {
Logger.getLogger(Player.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
class Referee implements Runnable{
public synchronized void check() throws InterruptedException {
while(true)
{
/****INITIALIZING THE GAME***/
while(a.getReady())
wait();
//If some player has won, releasing locks and exiting the threads
if(winner != 0)
{
a.putReady(true);
a.putFinish(true);
return;
}
//If the boards are full and ends in a draw
else if(count_plays >= 42)
{
System.out.print("\n Board is full. Its a draw!!\n");
a.putReady(true);
a.putFinish(true);
return;
}
//If there is more space on the board to play
else
{
System.out.print("\nNo player has won, let the play resume!!\n");
//Thread.sleep((long)100);
}
/* Code for checking if there has been a winner
*
*
*/
a.putReady(true);
notify();
}
}
#Override
public void run(){
try {
check();
}
catch (InterruptedException ex) {
Logger.getLogger(Player.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
`
I understand that threads of different objects cannot be synchronized and there is no point in serializing the code that is under synchronization. This is a task that I have been assigned. In the above code, Players play simultaneously even after providing a set of condition variables and do not allow thread of the referee to check for the winner each time they play.
Please, give me an outline of the code to provide such an output using synchronized method, notify() and wait().
It is allowed but rarely makes sense and would not make sense in your case. The two threads would be synchronizing on different objects which would have no effect. The point of the synchronized method is to prevent two threads from simultaneously accessing the same object. If the two players need to access some common object but you don't want the accesses to overlap you should synchronize on that object or synchronize one of the methods of that object. You should only be within a synchronized block or method for as little time as possible. synchronizing unnecessarily can lead to poor performance or deadlock.
The closest that made any sense to me was this:
a
public static class a {
static boolean finish = false;
public static void main(String[] args) throws InterruptedException {
finish = false;
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.execute(new Referee());
executorService.execute(new Player(1));
executorService.execute(new Player(2));
// wait for user to press enter, just for testing
new Scanner(System.in).nextLine();
executorService.shutdown();
executorService.awaitTermination(1, TimeUnit.MINUTES);
}
}
Player
public class Player implements Runnable {
final int playernum;
public Player(int playernum) {
this.playernum = playernum;
}
#Override
public void run() {
try {
while (!a.finish) {
synchronized (a.class) {
for (int i = 0; i < 5; i++) {
Thread.sleep(1000);
System.out.println("player " + playernum + " does step " + i);
}
}
Thread.sleep(1000);
}
} catch (InterruptedException interruptedException) {
}
}
}
Referee
public class Referee implements Runnable {
#Override
public void run() {
try {
while (!a.finish) {
synchronized (a.class) {
System.out.println("Check for winner.");
}
Thread.sleep(1000);
}
} catch (InterruptedException interruptedException) {
}
}
}
Notice that it is not synchronized during the entire run only during an internal block inside.
It should produce something like this:
Check for winner.
player 1 does step 0
player 1 does step 1
player 1 does step 2
player 1 does step 3
player 1 does step 4
Check for winner.
player 2 does step 0
player 2 does step 1
player 2 does step 2
player 2 does step 3
player 2 does step 4
Without synchronization you would not see all 5 steps from each player with no intervening checks or steps from the other player.
I just want to start and stop the thread when return key is pressed.
Here thread is stopped fine but i cant Start that thread again please help.
Also explain me the use of volatile keyword .Is it helpful for me to over come this problem.
public class Sync extends Thread{
public boolean meth= true;
public void run(){
while(meth){
System.out.println("hello");
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
}
}
}
public void shutdown(){
meth=false;
}
public void startup(){
meth=true;
}
}
MAIN CLASS``
package com.Sync;
import java.util.Scanner;
public class SyncMain {
public static void main(String[] arg) throws InterruptedException{
Sync hi= new Sync();
hi.start();
System.out.println("press enter to stop");
Scanner d= new Scanner(System.in);
d.nextLine();
hi.shutdown();
System.out.println("press enter to start");
d.nextLine();
hi.startup();
}
}
OUTPUT
run:
press enter to stop
hello
hello
hello
hello
press enter to start
BUILD SUCCESSFUL (total time: 6 seconds)
Thread's are not re-entrant, that is, once they exit the run method, they can't be restarted, you need to create a new instance.
One solution would be to create a new instance of Sync and start it, but a better solution, based on you code might, be to use a wait lock to "pause" the thread and the allow it to resume, for example...
public static class Sync implements Runnable {
private AtomicBoolean keepRunning = new AtomicBoolean(true);
private AtomicBoolean pause = new AtomicBoolean(false);
private ReentrantLock lckPause = new ReentrantLock();
private Condition conPause = lckPause.newCondition();
public void run() {
while (keepRunning.get() && !Thread.currentThread().isInterrupted()) {
while (pause.get() && !Thread.currentThread().isInterrupted()) {
lckPause.lock();
try {
System.out.println("Paused");
conPause.await();
} catch (InterruptedException ex) {
ex.printStackTrace();
} finally {
lckPause.unlock();
}
}
if (!Thread.currentThread().isInterrupted()) {
System.out.println("hello");
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
}
}
}
}
public void setPaused(boolean paused) {
if (pause.get() != paused) {
pause.set(paused);
if (!paused) {
lckPause.lock();
try {
conPause.signal();
} finally {
lckPause.unlock();
}
}
}
}
public void terminate() {
keepRunning.set(false);
setPaused(false);
}
}
This basically sets up two loops, one to keep the thread running until it's "terminated" and one to trap the "pause" condition...
Then you could do something like...
public static void main(String[] args) {
Sync hi = new Sync();
Thread t = new Thread(hi);
t.start();
Scanner d = new Scanner(System.in);
System.out.println("press enter to pause");
d.nextLine();
hi.setPaused(true);
System.out.println("press enter to resume");
d.nextLine();
hi.setPaused(false);
System.out.println("press enter to terminate");
d.nextLine();
hi.terminate();
try {
t.join();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
System.out.println("Has terminated");
}
to simply run it...
You should note that it's generally discouraged to extend directly from Thread and it is generally encouraged to use a separate Runnable, there are many reasons, but one which you will find most useful in future is Runnable is more widely supported in different parts of the API (like the Executors API) making it a much more flexible option
Have a look at the Concurrency Trail for more details, in particular Lock Objects
I am making a Java app which does something on a HotKey combination. I have an infinite while loop to wait for HotKey input to close, but it makes the app very CPU time costing.
Following is how my code looks in the simplest way:
static boolean isOpen = true;
void main()
{
....
add SomeHotKeyListener();
....
while(isOpen)
{ }
releaseResources();
}
void onHotKey(int hotKeyIdentifier)
{
if(hotKeyIdentifier == something)
do something;
if(hotKeyIdentifier == something)
isOpen = false;
}
I need a multi-threading approach to achieve this, or if someone has something better to fit in.
I recommend you read about the synchronized keyword in Java. Just Google it, and you should find a ton of examples and tutorials.
This should solve your case:
static boolean isOpen = true;
static Object lock = new Object();
void main()
{
....
add SomeHotKeyListener();
....
synchronized(lock)
{
while(isOpen)
{
try {
lock.wait()
} catch(InterruptedException e) {
}
}
}
releaseResources();
}
void onHotKey(int hotKeyIdentifier)
{
if(hotKeyIdentifier == something)
do something;
if(hotKeyIdentifier == something)
{
synchronized(lock)
{
isOpen = false;
lock.notify();
}
}
}
Infinite while loop can consume quite a lot of system resource. Using wait and notify is recommended. Also you have to declare your boolean volatile as otherwise there is no guarantee that the changes made by one thread is picked up by the other. Below is an example which does something in a separate thread and until interrupted by the calling thread based on a user input (an enter in this case). See also the example from Oracle here
import java.util.Scanner;
public class WaitTest implements Runnable {
private volatile boolean shutdown = false;
public static void main(String[] args) {
WaitTest w = new WaitTest();
new Thread(w).start();
System.out.println("Press any key to interrupt");
Scanner sc = new Scanner(System.in);
sc.nextLine();
w.triggerShutDown();
}
#Override
public void run() {
while (!shutdown) {
synchronized (this) {
try {
System.out.println("doing some silly things");
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
System.out.println("Server shutdown successfully");
}
public synchronized void triggerShutDown() {
this.shutdown = true;
notify();
}
}
I have a class which processes something. I'm trying to run a number of instances of this class in parallel.
However, I'm not sure if in TaskManager.startAll(), when I call r.go(), whether this would cause r to start running in its own thread, or within the main thread?
The total execution time that I'm getting seems to be very high, and despite my attempts at optimizing, nothing seems to be having any effect. Also, if I run a profiler on my project in Netbeans, it shows all the threads as sleeping. So I'd like to know if I'm doing something wrong?
This is the structure of the class:
public class TaskRunner implements Runnable {
private boolean isRunning = false;
public void run() {
while(true) {
while (! running) {
try {
Thread.sleep(1);
} catch (Exception e) {
e.printStackTrace();
}
}
process();
}
}
public void go() {
isRunning = true;
}
public void stop() {
isRunning = false;
}
private void process() {
//Do some number crunching and processing here
}
}
Here's how these are being run / managed:
public class TaskManager {
private ArrayList<TaskRunner> runners = new ArrayList<>();
public TaskManager() {
for (int i = 0; i < 10; i++) {
TaskRunner r = new TaskRunner();
new Thread(r).start();
runners.add(r);
}
}
public void startAll() {
for (TaskRunner r : runners) {
r.go();
}
}
}
Indeed, you are not "doing it right." If you want to create a multi-threaded Java application, the place to start is with the java.util.concurrent package.
It appears from your code that you want to run ten tasks in parallel. I assume that after "number crunching and processing," you'll want to aggregate the results and do something with them in the main thread. For this, the invokeAll() method of ExecutorService works well.
First, implement Callable to do the work you show in your process() method.
final class YourTask implements Callable<YourResults> {
private final YourInput input;
YourTask(YourInput input) {
this.input = input;
}
#Override
public YourResults call()
throws Exception
{
/* Do some number crunching and processing here. */
return new YourResults(...);
}
}
Then create your tasks and run them. This would take the place of your main() method:
Collection<Callable<YourResults>> tasks = new List<>(inputs.size());
for (YourInput i : inputs)
tasks.add(new YourTask(i));
ExecutorService workers = Executors.newFixedThreadPool(10);
/* The next call blocks while the worker threads complete all tasks. */
List<Future<YourResult>> results = workers.invokeAll(tasks);
workers.shutdown();
for (Future<YourResult> f : results) {
YourResult r = f.get();
/* Do whatever it is you do with the results. */
...
}
However, I'm not sure if in TaskManager.startAll(), when I call r.go(), whether this would cause r to start running in its own thread, or within the main thread?
So my first comment is that you should make isRunning be volatile since it is being shared between threads. If the threads are not starting when it goes to true (or seem to be delayed in starting) then I suspect that's your problem. volatile provides memory synchronization between the threads so the thread that calls go() and makes a change to isRunning will be seen immediately by the thread waiting for the change.
Instead of spinning like this, I would use wait/notify:
// this synchronizes on the instance of `TaskRunner`
synchronized (this) {
// always do your wait in a while loop to protect against spurious wakeups
while (!isRunning && !Thread.currentThread().isInterrupted()) {
try {
// wait until the notify is called on this object
this.wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
e.printStackTrace();
}
}
Then in the go() method you should do the following. stop() would be similar.
public void go() {
synchronized (this) {
isRunning = true;
this.notifyAll();
}
}
Notice that you should handle thread interrupts carefully. Test for isInterrupted() in the while running loop and re-interrupt a thread when InterruptedException is thrown is always a good pattern.
The total execution time that I'm getting seems to be very high, and despite my attempts at optimizing, nothing seems to be having any effect. Also, if I run a profiler on my project in Netbeans, it shows all the threads as sleeping.
So although the threads are mostly sleeping, they are still each looping 1000 times a second because of your Thread.sleep(1). If you increased the time sleeping (after making isRunning be volatile) they would loop less but the right mechanism is to use the wait/notify to signal the thread.
Awful solution, terrible. first I highly recommend you start reading some tutorial like [this]
Second, if threads should wait for a signal to go for some job, so why just don't you wait them!!!!!, something like this
import java.util.ArrayList;
public class TaskManager
{
//////////////////////
public volatile static Signal wait=new Signal();
//////////////////////
private ArrayList<TaskRunner> runners = new ArrayList<>();
public TaskManager()
{
for (int i = 0; i < 10; i++)
{
TaskRunner r = new TaskRunner();
new Thread(r).start();
runners.add(r);
}
try {
Thread.sleep(1000);
startAll();
Thread.sleep(1000);
pauseAll();
Thread.sleep(1000);
startAll();
Thread.sleep(1000);
haltAll();System.out.println("DONE!");
}catch(Exception ex){}
}
public void startAll()
{
synchronized(wait){
wait.setRun(true);;
wait.notifyAll();
}
}
public void pauseAll(){
wait.setRun(false);
}
public void haltAll(){
for(TaskRunner tx:runners){tx.halt();}
}
public static void main(String[] args) {
new TaskManager();
}
}
class TaskRunner implements Runnable
{
private Thread thisThread;
private volatile boolean run=true;
public void run()
{
thisThread=Thread.currentThread();
while(run){
if(!TaskManager.wait.isRun()){
synchronized(TaskManager.wait)
{
if(!TaskManager.wait.isRun()){
System.out.println("Wait!...");
try
{
TaskManager.wait.wait();
}
catch (Exception e)
{
e.printStackTrace();
break;
}
}
}}
process();
}
}
private double r=Math.random();
private void process(){System.out.println(r);try {
Thread.sleep(10);
} catch (Exception e) {
// TODO: handle exception
}}
public void halt(){run=false;thisThread.interrupt();}
}
class Signal{
private boolean run=false;
public boolean isRun() {
return run;
}
public void setRun(boolean run) {
this.run = run;
}
}
in above sample, all runners works till the Signal run boolean is true, and simple TaskManager class set tit as false for every time it needs to pause the threads. and about the halt, it just set the shutdown(run) flag to false, and also interrupt the thread because of if thread is in wait state.
I hope I could prove your solution is like dream-on story, and also could explained enough about my solution.
have a good parallel application :)