How to stop background thread, `interupt` not working - android

Consider this example:
Thread thread = new Thread(new Runnable() {
public void run() {
// Sleep for 5000ms
// Show toast message
}
});
Now I will start this thread on button click in MainActivity and right after that I would exit the activity on back button press, but in overided method onBackPressed following code is implemented:
If(thread != null)
thread.interupt();
finish();
After few seconds toast message is shown, why is that?

interrupt, clears the interrupt status of your thread and will cause the InterruptedException to be thrown. So if your thread is sleepin, and while it is asleep, you call interrupt, it will be woken up, and the execution flow will continue from the instruction that follows the catch block. Assuming you have something really simple like:
public void run() {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackThreace();
}
runOnUiThread(TOAST);
}
or
public void run() {
while(true) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackThreace();
}
runOnUiThread(TOAST);
}
}
both will shown the Toast even though you called interrupt()

While blackbelt has already explained the reason why this happens, here is how you can get around the problem.
The best way to interupt a thread is to use a if-boolean-break method.
So if i were to re-write you code it would be along the following lines
onBackPressed:
isBackPressed = true;
inside the thread's run method:
Thread thread = new Thread(new Runnable() {
public void run() {
// Sleep for 5000ms
if(!isBackPressed){
// Show toast message
}
}
});

Related

How to stop this thread?

I implemented this class in my android code
I made the below change in the run method(replaced "true"):
#Override
public void run() {
while (!isInterrupted()) {
try {
// A blocking operation. Initiate a ChatManager instance when
// there is a new connection
pool.execute(new ChatManager(socket.accept(), handler));
Log.d(TAG, "Launching the I/O handler");
} catch (IOException e) {
try {
if (socket != null && !socket.isClosed())
socket.close();
} catch (IOException ioe) {
}
e.printStackTrace();
pool.shutdownNow();
break;
}
}
}
I want to stop this thread before I close the app. So I implemented threadName.interrupt(); method. But this doesn't interrupt the thread.
I am actually confused with the usage of thread pool executor. So I am not sure how to do this efficiently. How can I implement interrupting this thread? When interrupt method is called, I want to close the socket, shutdown the pool and stop the thread.
Thread thread = new Thread () {
boolean isRunning = true;
public void stopThread() {
isRunning = false;
}
#Override
public void run() {
while (isRunning) {
try {
// A blocking operation. Initiate a ChatManager instance when
// there is a new connection
pool.execute(new ChatManager(socket.accept(), handler));
Log.d(TAG, "Launching the I/O handler");
} catch (IOException e) {
try {
if (socket != null && !socket.isClosed())
socket.close();
} catch (IOException ioe) {
}
e.printStackTrace();
pool.shutdownNow();
break;
}
}
}
};
thread.start();
Try this code. and call thread.stopThread() whenever you want the thread to stop.
if you want close an Android thread, you can set a variable to control run(),because run() is end, the thread will be closed.
The code is something like:
final boolean istrue=true;
new Thread(new Runnable() {
#Override
public void run() {
while (istrue){
//TODO your work
}
}
}).start();
}
If you want to close the thread, you only set istrue=false
Just call shutDownNow to close the pool and try interrupt all the threads inside it. You can check the difference in this post:
shutdown() will just tell the executor service that it can't accept new tasks, but the already submitted tasks continue to run
shutdownNow() will do the same AND will try to cancel the already submitted tasks by interrupting the relevant threads. Note that if
your tasks ignore the interruption, shutdownNow will behave exactly
the same way as shutdown.
If you want to interrupt or cancel an specific thread. I suggest you to use submit with Callables, With this, you will me able to work with your Future object, then if want to cancel a task you've given an executor service, you can call cancel(true) on its associated Future. When your task detects an interrupt request, it should preserve the interrupted status by calling Thread.currentThread().interrupt().

Correct way to run a continuously called method in own thread?

I'm calling methode doSomething() continuously with a thread.sleep(100). This happens in on the UIThread, so the UIthread gets unresponsive. What is the correct way in Android to run the method doSomething() or the entire someobject in a seperate thread?
public void loop(){
while(true){
someObject.doSomething();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Right now i'm using
new Thread(new Runnable() {
#Override
public void run() {
someObject.doSomething();
}
}).start();
This obviously creates a different thread for each iteration. I don't think this is the correct way. What is the correct way in Android?
new Thread(new Runnable() {
#Override
public void run() {
while(true){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
someObject.doSomething();
}
}
}).start();
Since run never returns, the thread will never end and will loop forever. It will call doSomething roughly every 100 ms (as close as sleep will get, which isn't exact).
You can make your own Thread class, with Looper and Handler, posting your doSomething every 100ms:
public class MyThread extends Thread{
private Handler myHandler;
#Override
public void run(){
Looper.prepare();
myHandler = new Handler();
myHandler.post(doSomethingRunnable);
}
Runnable doSomethingRunnable = new Runnnable{
doSomething(); //or myHandler.postDelayed() first for greater accuracy, but only if doSomething doesnt take too long
myHandler.postDelayed(doSomethingRunnable, 100);
};
doSomething(){
thisStuff(thatStuff());
}
}
You can use AsyncTask. doInBackground() is called on a background thread and will not block UI. This is the preferred way for doing stuff on background threads.
For a long running task. You can use an IntentService and put your background code in onHandleIntent
You can use a basic thread but it may be hard to manage. You can read more about threads in android here

getting java.lang.IllegalStateException: The current thread must have a looper

I am getting this error, and my application crashes:
java.lang.IllegalStateException: The current thread must have a looper!
I didn't get much about how to use looper on Google, I am using threads(mainly for sleep function), handler(for downloading the image while Async task is running) and Async task(for getting the JSON data from the URL). I have no idea how to resolve this issue, so any suggestions will be vey helpful.
This is the code for the thread which is executed on click of the button:
View view = flingContainer.getSelectedView();
view.findViewById(R.id.item_swipe_right_indicator).setAlpha((float) 1.0);
Thread timer = new Thread() {
public void run() {
try {
sleep(320);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
flingContainer.getTopCardListener().selectLeft();
}
}
};
timer.start();
I am using this libray and log-cat is:
where: at com.enormous.quotesgram.MainActivity$3.run(MainActivity.java:479) in last in log-cat corresponds to the line: flingContainer.getTopCardListener().selectLeft(); in above piece of code.
Try the following (unfortunately I cannot test the code):
Thread timer = new Thread() {
public void run() {
try {
sleep(320);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
runOnUiThread(new Runnable() {
#Override
public void run() {
flingContainer.getTopCardListener().selectLeft();
}
});
}
}
};
The idea behind is, that the Timer thread is not a Looper thread (resulting in an exception saying "The current thread must have a looper"). The UI thread however, is a Looper thread (see for instance this site).
As flingContainer.getTopCardListener().selectLeft() is probably designed to run on the UI thread it fails, if it not invoked in side of a pipelined thread.

Android- Thread.join() causes Application to hang

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.

to cancel a ongoing operation

i have two threads one for downloading and other for displaying data there is a cancel button in layout i want when i click cancel button the downloading thread stops how can i do this
final Thread parseThread=new Thread(new Runnable() {
public void run()
{
count=1;
searchResult.clear();
Log.v("url","++"+"http://wap.vinmonopolet.no/vareutvalg/sok?query="+v.getText());
Log.v("searchText","searchText "+ v.getText());
downloader("http://wap.vinmonopolet.no/vareutvalg/sok?query="+v.getText());
//if(msearchCancel)
}
});
parseThread.start();
Thread displayThread = new Thread(new Runnable() {
public void run() {
try {
if(msearchCancel)
parseThread.interrupt();
else
parseThread.join();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
mHandler.post(new Runnable() {
public void run()
{
list_ed=new EfficientAdapter(getApplicationContext());
searchList.setAdapter(list_ed);
progress_waiting1.setVisibility(ProgressBar.GONE);
}
});
}
});
displayThread.start();
First, use AsyncTask for tasks in own threads, it's much easier and handles some low level stuff for you.
Then, in your thread (or background task in AsyncTask), you need periodically to check that main thread requests cancel. In AsyncTask it is isCancelled method.
If you detect cancel request, you exit thread's function ASAP, so that thread may be closed. Otherwise, in case of AsyncTask.cancel, canceling is blocked until background task (thread) gracefully ends.

Categories

Resources