Android- Thread.join() causes Application to hang - android

I have a thread which handles my game loop, when i call .join() on this thread the application stops responding.
I've been trying to fix a problem where the programs never get to the code, I.E the thread never ends.
System.out.println("YAY");
My Thread for the Game Loop:
This thread successfully prints out "Game Ended" but never seems to finish.
Runnable startGameLoop = new Runnable() {//game loop
#Override
public void run() {
AiFactory ai = new AiFactory();
final Button play = (Button) findViewById(R.id.Play);
final Button pass = (Button) findViewById(R.id.Pass);
while(finish==false){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
currentPlayer = game.getPlayer();
if(currentPlayer.isPlayer()==false){
//System.out.println("passCount:" +game.getPasscount());
ai.decide(nextPlay, game.getPreviousPlayed(), currentPlayer, game.getPasscount() );
if(nextPlay.size()!=0){
runOnUiThread(new Runnable(){
public void run(){
changeArrow();
if(nextPlay.size() ==1){
play1Card();
}
else if(nextPlay.size()==2){
play2Card();
}
else if(nextPlay.size()==3){
play3Card();
}
else if(nextPlay.size()==5){
play5Card();
}
}
}
else{
game.addPassCount();
game.nextTurn();
runOnUiThread(new Runnable(){
public void run(){
changeArrow();
}
});
}
}
else if (currentPlayer.isPlayer()==true){
runOnUiThread(new Runnable(){
public void run(){
changeArrow();
play.setClickable(true);
if(game.getPasscount()==3){
pass.setClickable(false);
}
else{
pass.setClickable(true);
}
}
});
}
}
System.out.println("Game Ended");
}
};
Starting and joining the thread to the main thread:
Thread myThread = new Thread(startGameLoop);
myThread.start();
try {
myThread.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("YAY");
}
To my understanding .join() makes the current thread wait till the new thread has finished before carrying on.
Sorry if this is a stupid question, i'm quite new to threading.

When you call myThread.join() inside Activity.onCreate you block the main UI thread. Of course it looks like your application has stopped responding because the UI thread is the one responsible for redrawing UI. All your calls runOnUiThread never happen because your UI thread is busy waiting on your game loop.

Thread.join makes the current thread wait until the thread you call it on ends. It does not cause the thread you call it on to end. So if that thread is never ending (as you say at the top), calling join will make it hang forever.
If you want to actually end the thread, call cancel on it. But that requires your thread to occasionally call isCanceled() and exit its run function if it returns true.

mythread.join() does not ensure that your "mythread" is ended.
You need to place a notify() in your game loop.
...
...
System.out.println("Game Ended");
synchronized(mythread){
mythread.notify();
}
Basically, when you make a call to wait(), the code waits on the thread's monitor, and a call to notify() causes a thread waiting on the object's monitor to wake up.
Also, you can use notifyAll() to wake up all the waiting threads.
Alternatively, you can use timeout version of wait(), where the thread waits either till it gets notified or it times out.

Related

How to pause and resume a Thread?

I have a thread:
class SomeRunnable implements Runnable {
#Override
public void run() {
while (true) {
//some code...
try {
Thread.sleep(33);
} catch (InterruptedException e) {
return;
}
}
}
}
which I start using:
someThread = new Thread(new SomeRunnable());
someThread.setName("SomeThread");
someThread.start();
If I want to stop the thread I simply interrupt it:
someThreat.interrupt();
How can I later resume the thread?
Thank you!
You can use wait() and notify() method.
wait()
Causes the current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object. In other words, this method behaves exactly as if it simply performs the call wait(0).
notify()
Wakes up a single thread that is waiting on this object's monitor. If any threads are waiting on this object, one of them is chosen to be awakened. The choice is arbitrary and occurs at the discretion of the implementation. A thread waits on an object's monitor by calling one of the wait methods.

What will happen if I use try catch and finally for handler using runnable?

I use the code below for getting some work done everytime after some time interval, and using post delay in 'finally' clause and oustide of runnable. Here is the code.
Runnable runnable = new Runnable() {
#Override
public void run() {
try {
// do somthing
} catch (Exception e) {
// TODO: handle exception
} finally {
handler.postDelayed(this, 60000);
}
}
};
handler.postDelayed(runnable, 60000);
handler.postDelayed(runnable, 60000); will run two times or a single time.
it depends!
first matter
how the each try / catch / finally block completes normally or abruptly?
the finally block "always ^" executes when the try block exits
This ensures that the finally block is executed even if an unexpected exception occurs.
^ exception from above - finally may not be executed if jvm exits or thread gets killed
for details see java specs:
https://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.20.2
second matter
how Handler post/postDelayed method executes will pass? or fails? for some reason - for second this may happen if message was not placed in to the message queue - on failure, usually because the looper processing the message queue is exiting.
but most likely your statement will make a INFINITE loop
** ps. you need to throw an exception in try block or remove catch block (as try{} finally{} ) can exist "without" catch but code in catch block without rising any exception will make a compiler complain (code will not compile)
if you want loop n-times+1 you need to add some condition before postDelayed in Runnable run() method
in your case code flow execution:
postDelayed method from last line outside definition of runnable
execution of runnable by:
start of try block
with or without passing catch
through finally block with postDelayed in runnable run() method - wich will place runnable in message que for delayed execution on main thread
then infinite loop on 2
so should i remove last postDelay out side of run() method to achieve postDelay run only ones in one loop. – AndroidMob
you can write this in such way:
final Handler handler = new Handler();
handler.post(new Runnable() {
// this int will also be passed to method post delayed
// as "this" keyword applies to Anonymous Class
// which body contains everything between brackets of new Runnable() { ... }
int withThis = 1;
#Override
public void run() {
handler.postDelayed(this,1000);
}
});
so where should i call method to get done somthing ? in run() method..? – AndroidMob
this also depends what you want to achieve:
example
handler.post(new Runnable() {
int counter = 0;
#Override
public void run() {
boolean wasPlacedInQue = false;
doPreMethod();
if(counter =< 10) {
doMethod();
wasPlacedInQue = handler.postDelayed(this,1000);
}
if(wasPlacedInQue) {
counter++;
doPostyMethod();
} else doFailureMethod();
}
the code in run() method is executed synchronously on so called UI Thread - i'ts main thread which executes your application see:
https://developer.android.com/training/multiple-threads/communicate-ui.html
if you are interested to study it more I have made a full working example for you:
https://gist.github.com/c3ph3us/7d237d540e60597369856cb1fa652a23
it surely will run two times. Because they are two different messages and handler will handle them separately.

Will an infinite loop via handler block the UI thread?

I want to implement a timer in my android game using following code. This code runs certain code after every second.
final Handler handler = new Handler();
Runnable runable = new Runnable() {
#Override
public void run() {
try{
//task to be done
handler.postDelayed(this, 1000);
}
catch (Exception e) {
// TODO: handle exception
}
finally{
//task to be done
handler.postDelayed(this, 1000);
}
}
};
handler.postDelayed(runable, 1000);
The handler is created in UI thread. Will such an infinite loop block the thread ? If not why not ?
There is no loop and control returns to the UI thread looper that processes the message queue. It won't block the UI thread.
However, you're congesting the UI thread in other ways. Each invocation of the runnable re-posts itself twice: once in try and second time in finally, therefore effectively doubling the number of events in the message queue each second. Eventually the UI thread won't be able to do any useful work processing other events.

Handler postDelayed and Thread.sleep()

I have a thread.sleep and a handler postDelayed in my code:
handler.postDelayed(new Runnable() {
#Override
public void run() {
Log.e(TAG, "I ran");
mIsDisconnect = false;
}
}, DISCONNECT_DELAY);
After the handler code and after the user press the button I have this:
while (mIsDisconnect) {
try {
Thread.sleep(DELAY);
} catch (InterruptedException e) {
Log.e(TAG, "problem sleeping");
}
}
If the user wait long enough I can get the "I ran" in my log. But if the user press the button before the delay is up, it seems that the postDelayed never gets a chance to execute. My question is, does the thread.sleep() mess with the handler postDelayed?
Edit: The purpose of this code is that I want to continue the program only after DISCONNECT_DELAY seconds has already passed. So if the user clicks to early, I have to wait for the elapsed time to finish.
I'm assuming your handler is associated with the same thread the other loop is running on. (A Handler is associated with the thread it is created in.)
postDelayed() puts the Runnable in the handler thread's message queue. The message queue is processed when control returns to the thread's Looper.
Thread.sleep() simply blocks the thread. The control does not return to the Looper and messages cannot be processed. Sleeping in the UI thread is almost always wrong.
To accomplish what you're trying to do, remove the sleep and simply use postDelayed() to post a Runnable that changes your app state (like you already do by setting a member variable mIsDisconnect). Then in the onClick() just check the app state (mIsDisconnect flag) whether it is ok to proceed or not.
I guess that the second section runs on the main thread and you didn't move between threads.
You can't put the main thread on sleep, you stop all UI issues and other stuff that should be run on this thread (the main thread).
Use postDelayed of the handler instead.
The best way is with a sentinel:
runnable = new Runnable() {
#Override
public void run() {
// condition to pass (sentinel == 1)
if (isActive == 0) {
handler.postDelayed(this, 1000); // 1 seconds
}
else {
// isActive == 1, we pass!
// Do something aweseome here!
}
}
};
handler = new Handler();
handler.postDelayed(runnable, 100);

How to implement a paint-update loop?

I want to create a paint and update loop in android for game animation on a canvas but I am having trouble as I can't seem to get the threading to work appropriately. It seems to crash almost immediately. Here is what I have tried:
// Create the thread supplying it with the runnable object
Thread thread = new Thread(runnable);
// Start the thread in oncreate()
thread.start();
class runner implements Runnable {
// This method is called when the thread runs
long wait = 1000;
public void run() {
update();
}
public void update()
{
try{
Thread.currentThread();
//do what you want to do before sleeping
Thread.sleep(wait);//sleep for 1000 ms
//do what you want to do after sleeping
}
catch(InterruptedException ie){
//If this thread was interrupted by another thread
}
run();
}
}
Also when I drop the wait down lower it crashes faster.
Is there a more appropriate way to approach this?
Changed to this:
class runner implements Runnable {
// This method is called when the thread runs
long wait = 10;
boolean blocked = false;
public void run() {
if(!blocked){
blocked = true;
paint();
}
}
public void paint()
{
update();
}
public void update()
{
try{
Thread.currentThread();
//do what you want to do before sleeping
Thread.sleep(wait);//sleep for 1000 ms
//do what you want to do after sleeping
}
catch(InterruptedException ie){
//If this thread was interrupted by another thread
}
paint();
}
}
This results in the same error... :/
Well the first thing I notice is that run calls update and update calls run. This is going to cause a NO PUN INTENDED Stack Overflow. They call each other until the stacks fills up. Then it should crash.
You are missing your 'loop'.
You should NOT call run manually on an already started thread.
public void run()
{
while (true)
{
// do whatever
Thread.sleep(wait);
}
}
I would not actually use the above either, I'd use a Timer or Android equivalent. You should get the concept from this though.

Categories

Resources