I have the following code
package threads;
import java.util.ArrayList;
import java.util.List;
public class Threads extends Thread implements Runnable {
private final List<Thread> threadList = new ArrayList<>();
private String f, l;
private Thread greetings1, greetings;
public static void main(String[] args) {
String[] elements = { "Tim", "Fred", "Jeff", "Scott" };
Threads t = new Threads();
for (String e : elements) {
t.threadL(e);
t.threadR(e);
}
for (int index = 0; index < t.threadList.size(); index++) {
// blank at the moment
}
}
public void threadR(String f) {
greetings = new Thread(f);
Thread greetingsFromFred = new Thread(greetings) {
@Override
public void run() {
for (int i = 1; i < 5; i++) {
try {
System.out.println("Main Thread: " + i + " " + f);
Thread.sleep(5000);
} catch (InterruptedException ex) {
System.out.println("Main thread interrupted.");
}
System.out.println("Main thread exiting.");
}
}
};
greetingsFromFred.start();
}
public List<Thread> threadL(String l) {
greetings1 = new Thread(this);
this.l = l;
greetings1.start();
threadList.add(greetings1);
return (threadList);
}
@Override
public void run() {
greetings.interrupt(); // interrupt greetings thread here <-------
System.out.println("Greetings from " + l + "! threadL");
}
}
when threadL runs i want to interrupt threadR from running and therefore cause the
System.out.println("Main thread interrupted.");
to be printed from threadR
I have highlighted in my code where the interrupt should take place
greetings.interrupt(); //interrupt greetings thread here <-------
why is the interruption not working as it currently stands?
Your program is a bit of a maze of thread objects. Let's try to follow it from main
.
In main
, you create an object t
which is of type Threads
. This means it's a Thread
and a Runnable
.
Then, for each of your string, you run t
's threadL
and threadR
with that string as parameter.
Nowhere in main
do you actually start t
, or even run its run
method directly.
Then, in threadR
you create a new, empty Thread
and assign it to greetings
.
You then use that new empty Thread
(greetings) as a Runnable
that's being passed to a new Thread
object that also has its run
method overridden. This is rather futile. In any case, greetingsFromFred
is started, and will run the loop. But greetings
still contains that empty Thread
that has nothing to do with the greetingsFromFred
thread.
In threadL
you create yet another Thread
, to which you pass the current Thread
(which is t
in main
) as its runnable. You then finally start it. It will try to interrupt the thread in greetings
, but as we said, that's an inactive empty thread that was never started.
Your structure should be a lot less convoluted than that. As much as possible, use just Runnable
objects for things that should be executed. Thus, Threads
itself shoudld be a Runnable
, and threadR
should probably be fixed to something like this:
public void threadR(String f) {
Runnable greetingsFromFred = new Runnable() {
@Override
public void run() {
for (int i = 1; i < 5; i++) {
try {
System.out.println("Main Thread: " + i + " " + f);
Thread.sleep(5000);
} catch (InterruptedException ex) {
System.out.println("Main thread interrupted.");
}
System.out.println("Main thread exiting.");
}
}
};
greetings = new Thread(greetingsFromFred, f);
greetings.start();
}
This way, greetings
will be a Thread
which will run that loop that you have created in a Runnable
, and also have the name f
.
Note, though: since you don't actually stop the loop in your catch
clause, you won't exit the loop when the thread is interrupted, and you'll possibly have the "Exiting" message printed more than once, depending on when the interrupt hits the loop.