Search code examples
javamultithreadinginterrupt

Threads and interrupt


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?


Solution

  • 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.