Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android: Interrupt thread contained in a method

Tags:

java

android

In Android Studio, I have a thread contained in a method like so(seen below) because I would like to restart the thread whenever it is called[1] ,(recreating the thread rather than restarting)

public void callthread(){

   final Thread myThread = new Thread(new Runnable()
   {
       @Override
       public void run()
       {
           for (int x=0; x<750&&!Thread.interrupted(); x++) {
               //using this and thread sleep for repeated timed code within a thread

               try {
                   Thread.sleep(4);
                   runOnUiThread(new Runnable()
                   {
                       @Override
                       public void run() {

                           //some code

                           if (condition) {      
                               myThread.interrupt();
                           }
                       }
                   });

               } catch (InterruptedException e) {

               }
           }
       }
   });

My problem is that it wont let me use myThread.interrupt(); in the desired location in my code, giving me an error saying "variable 'myThread' may not have been initialized" and will not compile because of this. However it works when the entire thread is contained in class but I do not have a way of restarting it. In other words, I need a way to interrupt the thread while it is contained in a method.[2]

Accepted Solutions

[1]. A solution where the thread can be restarted

[2]. A solution where the thread can be interrupted while the thread is contained in a method

PS: If its unclear, I have edited my code above for easy readability but I have not removed things like the for loop or the Thread.sleep as I assume they could be part of the problem. So if theres too many or too little of a certain curly bracket then thats not the problem

EDIT: Searched around and apparently you cant restart a thread

like image 593
Mazino Avatar asked Aug 10 '15 22:08

Mazino


People also ask

How do you interrupt a method?

interrupt() method: If any thread is in sleeping or waiting for a state then using the interrupt() method, we can interrupt the execution of that thread by showing InterruptedException. A thread that is in the sleeping or waiting state can be interrupted with the help of the interrupt() method of Thread class.

What does thread Currentthread () interrupt () do?

Calling Thread. interrupt() is a way to tell the thread to stop what it is doing. If the thread is in a blocking call, the blocking call will throw an InterruptedException, otherwise the interrupted flag of the thread will be set. A Thread or a Runnable that is interruptible should check from time to time Thread.

What happens if the current thread is interrupted by another thread in thread InterruptedException ()?

If any thread is in sleeping or waiting state (i.e. sleep() or wait() is invoked), calling the interrupt() method on the thread, breaks out the sleeping or waiting state throwing InterruptedException.

How do you stop a thread from running on Android?

Whenever we want to stop a thread from running state by calling stop() method of Thread class in Java. This method stops the execution of a running thread and removes it from the waiting threads pool and garbage collected. A thread will also move to the dead state automatically when it reaches the end of its method.


3 Answers

You can start the interrupting thread in myThread before entering the for-loop. The interrupting thread sleeps 5 seconds and then interrupts myThread. The interrupt is handled in the exception handler. There the loop variable x is reset to 0, which is practically a restart of the loop.

public class ThreadInterruptRestart {

    public static void main(String[] args) {
        new ThreadInterruptRestart().callthread();
    }

    public void callthread() {

        final Thread myThread = new Thread("myThread") {
            @Override
            public void run() {
                final Thread _this = this;

                Thread interruptingThread = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            Thread.sleep(5000);
                        } catch (InterruptedException e) {
                            // this is not the interrupt we are interested in
                            e.printStackTrace();
                        }
                        if (true) {
                            System.out.println("interrupting " + _this + " from thread " + this);
                            _this.interrupt();
                        }
                    }
                }, "interrupting thread");
                interruptingThread.start();

                for (int x = 0; x < 750; x++) {
                    // using this and thread sleep for repeated timed code
                    // within a thread
                    try {
                        System.out.println(x);
                        Thread.sleep(10);
                    } catch (InterruptedException e1) {
                        // this is the interrupt we want to handle
                        System.out.println("" + this + " interrupted!");
                        // reset the loop counter
                        x = 0;
                    }
                }
            }
        };
        myThread.start();
    }
}

And another version where myThread does not sleep, and synchronization is used instead of an InterruptedException:

public class ThreadInterruptRestart {

    public static void main(String[] args) {
        new ThreadInterruptRestart().callthread();
    }

    public void callthread() {

        final Object mutex = new Object();

        final Thread myThread = new Thread("myThread") {
            @Override
            public void run() {
                final Thread _this = this;

                Thread interruptingThread = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            Thread.sleep(1);
                        } catch (InterruptedException e) {
                            // this is not the interrupt we are interested in
                            e.printStackTrace();
                        }
                        if (true) {
                            System.out.println("interrupting " + _this + " from thread " + this);
                            synchronized (mutex) {
                                _this.interrupt();
                            }
                        }
                    }
                }, "interrupting thread");
                interruptingThread.start();

                for (int x = 0; x < 75000; x++) {
                    // using this and thread sleep for repeated timed code
                    // within a thread
                    synchronized (mutex) {
                        System.out.println(x);
                        // do other stuff here
                    }
                    if (Thread.interrupted()) {
                        // this is the interrupt we want to handle
                        System.out.println("" + this + " interrupted!");
                        // reset the loop counter
                        x = 0;
                    }
                }
            }
        };
        myThread.start();
    }
}
like image 66
Lars Gendner Avatar answered Sep 29 '22 17:09

Lars Gendner


There are better ways of ending the thread. However if you have to access the thread use a reference variable like this:

 public void callthread(){

   final Thread myThread = new Thread(new Runnable()
   {
       @Override
       public void run()
       {
           final Thread _this = this;
           for (int x=0; x<750&&!Thread.interrupted(); x++) {
               //using this and thread sleep for repeated timed code within a thread

               try {
                   Thread.sleep(4);
                   runOnUiThread(new Runnable()
                   {
                       @Override
                       public void run() {

                           //some code

                           if (condition) {      
                               _this.interrupt();
                           }
                       }
                   });

               } catch (InterruptedException e) {

               }
           }
       }
   });
like image 36
MSD Avatar answered Sep 29 '22 18:09

MSD


The flaw in your code is "Leaking of this constructor" where you try to call the object's (in your case) thread's method before the thread has been instantiated.

To solve this you can go for a design similar to Observer pattern

like image 39
Abdul Rahman K Avatar answered Sep 29 '22 17:09

Abdul Rahman K