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
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.
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.
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.
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.
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();
}
}
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) {
}
}
}
});
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With