Wait for method to Finish, and weird interaction with System.println - java

I am trying to write a genetic program to play through a game, but I am running into a bit of a snag. When I call this code:
public double playMap (GameBoard gb, Player p) {
gb.playerController = p;
Game g = new Game(gb);
int initHP = 0;
for (Unit u : gb.enemy.units) {
initHP += u.maxHP;
}
g.playGame(false);
int finalHP = 0;
for (Unit u : gb.enemy.units) {
finalHP += u.currHP;
}
System.out.println(" " + initHP);
System.out.println(" " + finalHP);
System.out.println(" " + (finalHP - initHP));
if (initHP == finalHP) {
return -10;
}
return initHP - finalHP;
}
the g.playGame() line does not have time to finish, and I am getting incorrect results from the function. I can wait out unit the game is over with a
while (!g.isDone) {
System.out.println(g.isDone);
}
but not with the same while loop without a print statement. I know there has to be a more elegant solution, and I cant seem to implement the methods I have seen. Also if anyone knows why I need the print statement in the while loop to get it to wait that would be great too.
Thanks in advance.
ADDED playGame:
public void playGame(boolean visual) {
Global.visual = visual;
if (Global.visual) {
JFrame application = new JFrame();
application.setBackground(Color.DARK_GRAY);
application.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
application.add(this);
application.setSize(500, 400); // window is 500 pixels wide, 400 high
application.setVisible(true);
}
PlayerInput pi = new PlayerInput();
this.addKeyListener(pi);
final Timer timer = new Timer(10/60, null);
ActionListener listener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
pi.addPressed();
if (update(pi)) {
// application.setVisible(false);
// application.dispose();
System.out.println(gb.toString());
isDone = true;
timer.stop();
}
pi.reset();
}
};
timer.addActionListener(listener);
timer.start();
while (!isDone) {
System.out.println(isDone);
}
}

First of all, this is a really bad way of doing this. This approach is called "busy waiting" and it is very inefficient.
The problem is most likely that reads and writes to g.isDone are not properly synchronized. As a consequence, there are no guarantees that the "waiting" thread will ever see the update to g.isDone that sets it to true.
There are various ways to ensure that the update is seen. The simplest one is to declare isDone as volatile. Another one is to do the reads and writes within a primitive lock.
The reason that the println() call "fixes" things is that println is doing some synchronization behind the scenes, and this is leading to serendipitous cache flushing (or something) that makes your update visible. (In other words: you got lucky, but exactly how you got lucky is hard to tie down.)
A better solution is to use another mechanism for coordinating the two threads.
You could use Thread.join() so that one thread waits for the other one to terminate (completely!).
You could use a Latch or Semaphore or similar to implement the waiting.
You could use an Executor that delivers a Future and then call Future.get() to wait for that to deliver its result.
You could even use Object.wait and Object.notify ... though that is low-level and easy to get wrong.
Without seeing the full context, it is hard to judge which approach would be most appropriate. But they would all be better than busy-waiting.
Another answer says this:
If you remove the System.out.println() call from your loop, I believe that the compiler simply doesn't include the loop in the Java bytecode, believing it to be superfluous.
As I explained above, the real problem is inadequate synchronization. To be technical, there needs to be a happens-before relationship between the write of isDone in one thread and the read of isDone in the other one. Various things will give that ... but without that, the compiler is entitled to assume that:
the writing thread does not need to flush the write to memory
the reading thread does not need to check that the memory has changed.
For example, without the happens-before, the compiler would be permitted to optimize
while (!g.isDone) {
// do nothing
}
to
if (!g.isDone) {
// do nothing
}
We don't know if this actually happens, or whether the actual cause of "non-visibility" of the update to isDone is something else. (Indeed, it could be JVM version / platform specific. To be sure, you would need to get the JIT compiler to dump the native code for the methods, and analyze the code very carefully.)

Apparently you are running your game in a separate thread. Assuming that thread is called foo, calling foo.join() will block the calling thread until foo finishes executing. You can simply replace your entire loop with foo.join().
If you remove the System.out.println() call from your loop, I believe that the compiler simply doesn't include the loop in the Java bytecode, believing it to be superfluous.

Related

Program not terminating after loop completion

In the following scenario, the boolean 'done' gets set to true which should end the program. Instead the program just keeps going on even though the while(!done) is no longer a valid scenario thus it should have halted. Now if I were to add in a Thread sleep even with zero sleep time, the program terminates as expected. Why is that?
public class Sample {
private static boolean done;
public static void main(String[] args) throws InterruptedException {
done = false;
new Thread(() -> {
System.out.println("Running...");
int count = 0;
while (!done) {
count++;
try {
Thread.sleep(0); // program only ends if I add this line.
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
Thread.sleep(2000);
done = true; // this is set to true after 2 seconds so program should end.
System.out.println("Done!"); // this gets printed after 2 seconds
}
}
EDIT: I am looking to understand why the above needs Thread.sleep(0) to terminate. I do not want to use volatile keyword unless it is an absolute must and I do understand that would work by exposing my value to all threads which is not my intention to expose.
Each thread have a different cached version of done created for performance, your counter thread is too busy making the calculations for count that it doesnt give a chance to reload done.
volatile ensures that any read/write is done on the main memory, always update the cpu cache copy.
Thread.sleep always pause the current thread, so even if 0 your counter thread is interrupted by some time <1ms, that is enough time for the thread to be adviced of done variable change.
I am no Java expert man, I don't even program in java, but let me try.
A thread on stackoverflow explains the Java Memory model: Are static variables shared between threads?
Important part: https://docs.oracle.com/javase/6/docs/api/java/util/concurrent/package-summary.html#MemoryVisibility
Chapter 17 of the Java Language Specification defines the
happens-before relation on memory operations such as reads and writes
of shared variables. The results of a write by one thread are
guaranteed to be visible to a read by another thread only if the write
operation happens-before the read operation. The synchronized and
volatile constructs, as well as the Thread.start() and Thread.join()
methods, can form happens-before relationships.
If you go through the thread, it mentions the "Happens before" logic when executing threads that share a variable. So my guess is when you call Thread.sleep(0), the main thread is able to set the done variable properly making sure that it "Happens first". Though, in a multi-threaded environment even that is not guaranteed. But since the code-piece is so small it makes it work in this case.
To sum it up, I just ran your program with a minor change to the variable "done" and the program worked as expected:
private static volatile boolean done;
Thank you. Maybe someone else can give you a better explanation :P

Is this a safe way to synchronize a block of code?

In our application, there's a section of code that runs continuously reading and adjusting files. Just to give you a sense of what's going on:
public void run() {
try {
while(true) { //Yeah, I know...
Path currentFileName = getNextFile();
String string = readFile(currentFileName);
Files.deleteFile(currentFileName);
string = string.replaceAll("Hello", "Blarg");
writeFile(currentFileName);
}
} catch (Exception e) {
System.err.println("It's all ogre now.");
e.printStackTrace(System.err);
}
}
Elsewhere in our code is a method that might-but-usually-doesn't run on the same thread as the above code, that we use to exit the application.
private void shutdown() {
if(fileReader != null)
fileReader = null;
System.exit(0); //Don't blame me, I didn't write this code
}
As might be obvious, there's a potential Race Condition in this code, whereby if shutdown() is called between retrieving the file and then writing it back out, it'll potentially cause the file to be completely lost. This is, obviously, undesirable behavior.
There's a thousand issues with this code (outside the scope of just what I've shown here), but the main issue I need to resolve is the bad behavior where processing a file can be cut off halfway through with no recourse. My proposed solution involves simply wrapping the while loop in a synchronized block and putting a block around the System.exit call in shutdown.
So my changed code would look like this:
private Object monitor = new Object();
public void run() {
try {
while(true) {
synchronized(monitor) {
Path currentFileName = getNextFile();
String string = readFile(currentFileName);
Files.deleteFile(currentFileName);
string = string.replaceAll("Hello", "Blarg");
writeFile(currentFileName);
}
}
} catch (Exception e) {
System.err.println("It's all ogre now.");
e.printStackTrace(System.err);
}
}
private void shutdown() {
synchronized(monitor) {
if(fileReader != null)
fileReader = null;
System.exit(0);
}
}
The main thing I'm worried about is the System.exit(0); call, where I'm not certain about the total behavior behind the scenes of the call. Is there a risk that a side-effect of System.exit will be to release the lock on monitor, and thus risk the contents of the loop in run being executed partially before System.exit has caused the JVM to halt? Or will this code guarantee that the execution will never attempt a shutdown part-way through the handling of an individual file?
Note: before some armchair programmers step in with alternatives, I'd like to point out that what I've put here is a truncated version of about 4000 lines of code all stashed in a single class. Yes, it is awful. Yes, it makes me regret my chosen profession. I am not here looking for alternate solutions to this problem, I am only trying to determine if this specific solution will work, or if there's some critical flaw that would preclude it from ever working as I expect.
Or will this code guarantee that the execution will never attempt a shutdown part-way through the handling of an individual file?
This code guarantees that a shutdown initiated here will not occur part-way through handling of an individual file. Perhaps obviously, somewhere else in your code could invoke System.exit, and you have no protection from that.
You might want to consider preventing System.exit from being invoked, and then cause your code to shut down gracefully (i.e. by normal completion of the main method).
In case you really have multiple threads calling the different methods, using synchronized like this is actually a clever idea, as it takes care of that "multiple threads" thing.
You could consider reducing the scope of the first block:
Path currentFileName = getNextFile();
String string = readFile(currentFileName);
synchronized(monitor) {
reading the file alone shouldn't be a problem. (of course, unless your code here has to guarantee that a Path returned by getNextFile() gets fully processed).
If the code is executing in the synchronized block and the blocks synchronize on the same object, and the methods invoked in the synchronized block in the while loop operate entirely on the same thread as their caller, then there is no risk of the file-related processes being interrupted by that invocation of System.exit.
This said, it does look like a debatable patch only slightly improving debatable code.
There may also be a more concrete risk of starvation, as the while loop as displayed just seems to spam those file operations as fast as possible, hence the attempt to acquire the lock when exiting may not succeed.
A general direction to explore would be to transform the infinite while loop into a ScheduledExecutorService + Runnable, executing every x amount of time with its own monitor to prevent overlapping operations on the same file(s), and gracefully terminating it when the shutdown method is invoked.
You could use a shutdown hook. From the javadocs:
A shutdown hook is simply an initialized but unstarted thread. When the virtual machine begins its shutdown sequence it will start all registered shutdown hooks in some unspecified order and let them run concurrently.
https://docs.oracle.com/javase/7/docs/api/java/lang/Runtime.html#addShutdownHook(java.lang.Thread)
From this, you could provide a shutdown hook from your file class as follows:
public Thread getShutdownHook() {
return new Thread(() -> {
synchronized (monitor) {
// gracefully handle the file object
}
});
}
This will be called when Runtime.getRuntime().exit() is called (which is called by System.exit()). Since it is also synchronized on the monitor object, if the file is in use by the other thread, the shutdown hook will block until it is free.
Even if you cope with concurrent System.exit(), other reasons remain which can lead to sudden break of execution, like power outage or hardware error.
So you better do not remove the file before the new version is written. Do something like:
Path currentFileName = getNextFile();
Path tmpFileName = currentFileName+suffix();
String string = readFile(currentFileName);
string = string.replaceAll("Hello", "Blarg");
writeFile(tmpFileName);
Files.move(tmpFileName, currentFileName);

is it guaranteed that threads will resume in the order they were suspended/blocked by wait() in Java?

Suppose my program uses three threads. The first two threads are blocked using wait(), then the third thread comes and resumes both of them. When the third thread frees the two threads, it creates a race condition between those two threads (please correct me if I am wrong). Here is a program I wrote to illustrate this:
class Callee {
static boolean doBlock = true;
void callMe (int index) throws InterruptedException {
//suspend the first two threads
if (index < 3 && doBlock) {
wait();
}
System.out.println("The index is: " + index);
//let the third thread resume both of them
if (index == 3) {
doBlock = false;
notifyAll();
}
}
}
class Caller implements Runnable {
final int threadIndex;
final Thread thread;
final Callee callee;
Caller(int index, Callee c) {
threadIndex = index;
callee = c;
thread = new Thread(this);
thread.start();
}
#Override
public void run() {
synchronized (callee) {
try {
callee.callMe(threadIndex);
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
}
}
public class App {
public static void main(String[] args) throws InterruptedException {
Callee c = new Callee();
Caller caller1 = new Caller (1, c);
Caller caller2 = new Caller (2, c);
Caller caller3 = new Caller (3, c);
caller1.thread.join();
caller2.thread.join();
caller3.thread.join();
}
}
Each time I run the above program on my Windows machine, I get consistent output:
The index is: 3
The index is: 1
The index is: 2
Note that the first thread was freed before the second thread. Also note that I did not set priorities to any of those threads. I ran it at least ten times but results are not changing. I'm curious if it's my OS or does Java always resume the thread that was blocked first?
Short answer
No, there is no guarantee that they will resume in order so you shouldn't build any logic based on that even if the behavior was validated multiple time by multiple people, but you had a great idea of asking instead of just assuming.
Long answer
What could be happening is that this is how threads behave on Windows specifically; if the threading is fully handled by the SO itself, it might even be a behavior specific to your specific version of Windows. In that case, because Java works on multiple OS and each OS could behave differently, then Java cannot guarantee a behavior across all environments and therefore makes no promises about it.
It could also just be a behavior of that specific version of the JVM and Sun/Oracle never wanted to commit to a specific behavior, this means that even if this behavior was to be constant in the current JVM version, because it was never part of the formal "contract" they could reserve the right to change it at any moment without prior notification.
In either cases, what could happen if you decide to build logic on top of it is that the code simply wouldn't work properly on another OS or, even better, stop working properly after an OS update or JVM update (even minor ones).
An example of that happened in a company I've worked for a few years back; it used to be that Oracle (the RDBMS) used to automatically sort your results by your GROUP BY criteria if you didn't specify any (it was never part of the SQL standard, nor ever specified in any Oracle document, everyone just noticed it worked like that) ... in their infinite wisdom, many people started just skipping the ORDER BY clause if they used group by. Then came a new Oracle version (might have been 9i or 10g) and they just stopped auto-sorting the results which resulted in millions of $$$ being wasted going over ALL applications to inspect the code and then re-doing test (tests were not automated of course).
No it is not guaranteed unless you use a fair lock with a condition rather than a wait/notify.
The lock you obtain by synchronized is not fair.

Why won't this 'if' statement run in a while loop without something else also happening in the while loop?

I'm having a problem where an if statement is only running if there is something else happening before it in the while loop.
Here is the code I want to use:
public void load() throws IOException, InterruptedException {
while (true) {
if (findGame == true) {
System.out.println(findGame);
}
}
}
That is simplified but it shows my problem. Basically, when findGame == true, the if statement does not run. The reason I don't think the if statement is running is because the variable is not being printed out to the console.
I did some tests and found that the if statement ran with the following code:
public void load() throws IOException, InterruptedException {
while (true) {
System.out.println("foo"); // New code added
if (findGame == true) {
System.out.println(findGame);
}
}
}
My question is why does it work with the above code but not the first one? The only difference between the two is that the one that works has something else added to the while loop.
If it makes a difference, the code I've shown above is running in a separate thread.
If it makes a difference, the code I've shown above is running in a separate thread.
And that's the problem. You're relying on a value set by one thread to be visible in another - and there's no such guarantee without memory barriers being involved. In your second code, the call to println is almost certainly responsible for creating the memory barriers required for the reading thread to "see" the value written by the writing thread. Memory models are hard, unfortunately :(
If you use AtomicBoolean instead of just a boolean field, you may well find the first code works instead - but even so, a tight loop is generally a bad idea. It would be better to use a semaphore or some similar kind of signalling, so the "reading" thread could just wait (idly) until there's a change. Look into java.util.concurrent for classes such as Semaphore and CountDownLatch. (You can do it with just wait and notify, but it'll be simpler if you use higher-level abstractions.)

Java - terminating a method within a Thread

I have a Java thread with a run method that computes many things. You can think of it as a series of math statements as follows. Note that each computation may utilize other methods that in turn might have additional loops and such.
public void run() {
[computation 1 goes here here that takes a few seconds]
[computation 2 goes here that takes a few seconds]
....
[computation 30 goes here that takes a few seconds]
}
There is a GUI that prints the output of these statements as they produce their results, and I'd like the user to be able to say "Stop" whenever they want. Here are two methods I thought of
Method 1: Many Boolean Checks [LOOKS TERRIBLE]
private boolean stop;
public void run() {
if(!stop)
[computation 1 goes here here that takes a few seconds]
if(!stop)
[computation 2 goes here that takes a few seconds]
....
if(!stop)
[computation 30 goes here that takes a few seconds]
}
In this method, once the stop flag has been set to true, the computations will end. Note how silly this looks, having 30 if statements. Importantly, the critical question here is how often to put these conditions. Note that the computations on each line are not necessarily a single line. Taken to the extreme, does EVERY line in the run() method deserve a if(!stop) call above it? This doesn't seem like good design.
Method 2: Generalizing Computations [CANNOT DO THIS]
pirivate boolean stop;
public void run() {
for(int i = 0; i < computationsN && !stop; i++) {
computuations.get(i).compute();
}
I imagine that this method will be suggested, so I'd like to simply state that it is impossible in my case, given the sheer variation in the lines that I am calling "computations" for simplicity. I have typically done this for threads that are basic while loops, and it works great for such. But not in this case when the run() method is simply a huge method of variable code.
Any other solutions out there? Seems like this should be a universal problem. Thanks in advance!
what you want to do actually could be done with method 2, but you have to use the Strategy Pattern, is really the one more thing you need, because it make it possible to simplify your computations in one single line, like you actually did in Method 2.
It works like this, it lets you to change the next executable algorithm by doing polymorphism.
So first you have to make all your algorithms in different classes and each one has to implement one interface (it could be called Computable ) with one single method, that is, your compute() method.
Ex.
public interface Computable {
public void compute();
}
And your Algorithms classes could be something like:
public class AlgorithmX implements Computable {
#Override
public void compute() {
// TODO Your Real Computation here for the Algorithm X
}
}
Then in your for Loop your computations Collection (or Array) is populated with Objects that implements Computable, i.e., with your Algorithms Objects.
for(int i = 0; i < computations && !stop; i++) {
computuations.get(i).compute();
}
So you are in the right path with Method 2, I hope your way is more clear now.
Cheers!
Instead of using a stop flag you can call interrupt() on the thread to halt it, and inside your run method check to see if (Thread.interrupted()) is true (interrupt() doesn't immediately halt the thread, you've still got to check for Thread.interrupted()). This way you avoid pitfalls like forgetting to declare your flag as volatile.
http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Thread.html#interrupt%28%29
Short of encapsulating all of your computations in Runnables then putting them in an array and looping over them, which you've ruled out, Method 1 is your best bet. As for how often you should check to see if your thread is interrupted, that depends on how long it takes your computations to run and how responsive you want your program to be to a Stop command - you can add several println(System.currentTimeMillis) statements to get an idea of the computations' timing, then add an if(Thread.interrupted()) return; every 500 milliseconds or so to halt the run method.
I wouldn't immediately rule out Method 2, however, as your computations don't need to have anything in common in order for you to put them in Runnables
private ArrayList<Runnable> runnables = new ArrayList<>();
runnables.add(new Runnable() {
public void run() {
// computation 1
}
})
runnables.add(new Runnable() {
public void run() {
// computation 2
}
})
// etc
public void run() {
for(Runnable runnable: runnables) {
if(Thread.interrupted()) return;
runnable.run();
}
}
Depending on how your GUI is structured, is there any chance that you could throw an exception (probably an interruptedexception) from the GUI code that would blow out the long process?
The key thing is to look for somewhere in your code flow where things bottleneck to a point where a check could be inserted. This may not be super obvious (for example, you could hook the repaint manager in a swing app) - and it is definitely not good practice in the general case - but for a very specific use-case, it may be appropriate.
If that's not possible, a slightly less verbose approach would be to use a method like this:
assertContinue() throws InterruptedException;
(or maybe call it ac() to keep the typing down).
you still wind up with cruft in your algorithm, but at least it's less typing.
Oh - and what are these calculations? Are they blocking b/c of IO or locks somehow? If so, then calling Thread.interrupt() will work...

Categories