Java - terminating a method within a Thread - java

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...

Related

Can a thread lose control after calling a method but before the first instruction of the method?

I need to record the exact order in which a method is called by various threads in Java. I'm supposed to use an object timeProvider which returns non-decreasing long integers. The solution I have come up with is:
public synchronized void method() {
long order = timeProvider.getTime();
// some stuff that can be run concurrently
}
Of course it is a bottleneck because the only place I need to use synchronization is the first line.
So I'm wondering whether it would be safe to change the code to:
public void method() {
//(1)
synchronized (timeProvider) {
long order = timeProvider.getTime();
}
// some stuff that can be run concurrently
}
But in this version I'm worried that the running thread A could lose control in the place marked as (1) - inside the method but before the first instruction. Then another thread B could call the method after A has called it and execute the first intruction and as a result the order from the timeProvider would be recorded wrong. Is this possible?
Yes: The thread executing code inside a method can be halted before the first line.
It might appear as if nothing happens by just calling the method, but actually much happens, especially the creation of the stack frame.

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

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.

Confused about how I should handle my looping thread

I'm currently confused on how I should solve a certain problem:
I have a thread, whose run() method approximately looks like this:
#Override
public void run() {
running = true;
while(running) {
foo(x);
draw(x);
}
}
Now this foo does something with variable x.
In the main thread theres a listener executing a method, which also changes x
#Override
public void mouseDragged(MouseEvent e) {
bar(x);
}
The problem is now, that sometimes x gets modified by the bar(x) method, while foo(x) also changes x, which messes x up.
What I think could be done to fix this is for the listener, when firing, to wait for the loop to reach its end, execute its method and bar(x) while letting the thread wait and then notify the thread to let it continue looping after that.
I'm not very experienced with thread-handling though and would appreciate it, if someone helped me out. Sorry if this problem is really easy to solve and I just can't see the solution.
You should make x an AtomicInteger (a thread-safe wrapper for Integers) and use it's methods to update and retrieve it in bar(), foo(), and draw().
Some of the key methods here are incrementAndGet() (like ++x), getAndIncrement() (like x++). More here at the JavaDocs:
http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/AtomicInteger.html
Java 8 added a whole lot more to that interface for atomically doing larger calculations as well.
AtomicInteger may not be the correct type. I'm guessing it based on guessing that x is an int in your example.
Nevermind guys, I just had to synchronize the methods of x, which got called by the loop and the listener.
I should've represented the accessing of x by saying x.foo() and x.bar(), sorry for the unclear question.

Looping in Threads

Consider the following two designs of run method:
Approach A
public void run() {
do {
//do something
} while (condition);
}
Approach B
public void run() {
//do something...
if (condition) {
new Thread(this).start();
}
}
The second approach seems cleaner to me, after some debate, I have been told it's not a good idea to use approach two.
Question:
What are reasons (if there is any) that I shouldn't be using approach 2?
You have two things here. A loop, and a method that continuously runs itself again in a new thread until a condition is met (not a loop).
If you need a loop, you would choose the standard normal loop that everyone understands and works perfectly.
If you need to write a weird piece of code that creates new threads for no reason, and makes other developers doubt your skills and understanding, you would go for option B.
There's absolutely no sense in your choice B unless there would be something additional like a queue or ThreadPoolExecutor involved for re-invoking the method, so the method would add this at the end for invocation at a later time, sort of like a "lazy loop".
Because approach B uses one more thread than approach A. Creating threads is expensive, for a number of reasons #see Why is creating a Thread said to be expensive?
Approach A is also a little clearer to the reader, IMO. The simplest option usually is.
The 2nd option creates a new thread every time it is iterated, so it ends up being unnecessarily costly, especially when option A does the same thing but doesn't create new threads for every iteration.
The only good use-case I can find for Pattern B is if there is a significant delay before you want to re-run the method. For example for some kind of polling system that is supposed to run every X minutes until the system is being shut down.
In that case, using a scheduler instead of a Thread.sleep(fiveMinutes) makes sense to avoid tieing up resources unnecessarily (maybe you are holding on to a database connections or such).
Note that in that case, you'd be using a scheduler, not just Thread#start, so I am allowing for a rather liberal interpretation of Pattern B.
They will behave very differently.
The first solution will loop until condition is false and then terminate.
The second solution will start a new thread and die until condition is false. It will likely accomplish what you want to do but it will waste a lot of resources allocating and destroying new threads.
Here's an example that loops over 5 values and prints the value and current thread name:
Loop:
Runnable loop = new Runnable() {
int i = 0;
#Override
public void run() {
do {
System.out.printf("%s: %s%n", Thread.currentThread().getName(), i);
i++;
} while(i < 5);
}
};
loop.run();
main: 0
main: 1
main: 2
main: 3
main: 4
Threaded:
Runnable thread = new Runnable() {
int i = 0;
#Override
public void run() {
System.out.printf("%s: %s%n", Thread.currentThread().getName(), i);
i++;
if(i < 5) {
new Thread(this).start();
}
}
};
thread.run();
main: 0
Thread-0: 1
Thread-1: 2
Thread-2: 3
Thread-3: 4
As you can see, the threaded example prints each line on a different thread which is very wasteful and probably not what you want to accomplish.

Are unresettable "flags" threadsafe in Java?

I have been using this pattern for a while, but I only recently came to think that it might not be OK to do this. Basically, I use some variant of this pattern:
public class SampleJavaAsync
{
public SampleJavaAsync() { }
private boolean completed;
public void start()
{
new Thread(new Runnable() {
#Override
public void run() {
//... do something on a different thread
completed = true;
}
}).start();
}
public void update()
{
if (!completed) return;
//... do something else
}
}
*The user is responsible for making sure start is only called once. update is called wherever and whenever.
I've always assumed this is threadsafe in Java, because even though nothing is strictly synchronized, I only ever set completed to true. Once it has been observed to be true, it will not reset to false. It is initialized to false in the constructor, which is by definition thread safe (unless you do something stupid in it). So, is it thread safe to use unresettable flags in this way? (And if so, does it even provide any performance benefits?)
Thanks
Java: it's feasible for update() to not see the update to completed that has already happened. Unless you mark it volatile, the JVM is permitted to do all sorts of things in the name of optimization (namely reordering reads and writes as it sees fit), meaning you could feasibly hit a state where the thread running update() NEVER sees that completed has changed, because it's not marked volatile, and it thinks it can optimize away that pesky write (or defer it).
You would at least run the risk of having inconsistency when it's first set, where, e.g. a call to update() on the same thread could see a different value than the same call from another thread, at the same time.
Better explained:
http://jeremymanson.blogspot.com/2008/11/what-volatile-means-in-java.html
Or, if you're really curious about concurrency in Java, buy a copy of JCIP:
http://jcip.net.s3-website-us-east-1.amazonaws.com/

Categories