Kristian Martinsen
Kristian Martinsen

Reputation: 95

Defining a thread id to a object and interrupt

I have threads dedicated to users on a system, and I want to be able to stop them individually, do I store the ID of the thread with the userdata at creation and then call an interrupt? or can I somehow add the thread to my user objects and just call it like myuser.mythread.interrupt(); or is this whishing for magic?

Currently I can stop them all and restart without the thread I want. But that is a time consuming task and also triggers a lag where users must wait.

Update, can this be an answer?

if(delete==true) {
    if (Thread.currentThread().getId() == deleteId) {
        Thread.currentThread().interrupt();
        delete=false;
    }
} 

Update

I managed to find a way to use myuser.mythread.interrupt(); Or sort of..

I added the thread as a sub class to the user class and created a method in the user class to start and interrupt, now i can start and stop threads with

online.get(1).hellos();
online.get(1).hellosStop();

Instead of having to create a reference and keeping track of anything else than the user objects.

Update (regarding accepted answer, using the id as a reference I could do it this way)

public class MyRunnable implements Runnable {
    private boolean runThread = true;
    @Override
    public void run() {
        try { 
            while (runThread) {
               if(delete==true) {
                   if (Thread.currentThread().getId() == deleteId) {
                       Thread.currentThread().interrupt();
                       delete=false;
                   } 
                }
                Thread.sleep(5);
            }
        }
        catch (InterruptedException e) {  
            // Interrupted, no need to check flag, just exit
            return;
        }
    }
}

Upvotes: 0

Views: 611

Answers (2)

Stephen C
Stephen C

Reputation: 719446

The best approach is to save the Thread reference and make it available to the code that needs to interrupt it.

It is technically possible (for a non-sandboxed application) to traverse the tree of all of the JVM's existing threads testing each one. However, that is expensive and doesn't scale. And if you can store or pass the id of a thread, then you should be able to store or pass the Thread reference instead.

It is also technically possible to create your own WeakHashMap<Long, Thread> and use that to map thread ids to threads. But the same argument applies ....

You ask if this is a solution:

if (delete) {
    if (Thread.currentThread().getId() == deleteId) {
        Thread.currentThread().interrupt();
        delete = false;
    }
} 

No it isn't. Or more precisely, it will only "work" in the case where the thread is interrupting itself. In other cases, the target thread won't be interrupted.


Depending on your use-case, another way to do this could be to use an ExecutionService rather than bare threads. The submit methods return a Future object that represents the submitted task. The object has a cancel(...) method that can be used to cancel the task, either before it runs, or by interrupting the running thread.

Upvotes: 0

john16384
john16384

Reputation: 8064

You can just store the Thread reference, perhaps in a WeakReference so that the thread will go away if it exits on its own.

But you can also have the Thread check an AtomicBoolean (or volatile boolean) every now and then to see if it was interrupted, that way you don't need a reference to the thread.

Note though that stopping threads in Java is not possible without cooperation from the thread you want to stop. It doesn't matter if you use interrupt or a boolean that it checks, in both cases it is up to the thread to check these flags (interrupt just sets a flag) and then perform some action like exiting.

Update A sample interruptable thread class:

public class MyRunnable implements Runnable {
    private final AtomicBoolean stopFlag;

    public MyRunnable(AtomicBoolean stopFlag) {
        this.stopFlag = stopFlag;
    }

    @Override
    public void run() {
        try { // Try/Catch only needed if you use locks/sleep etc.
            while (!stopFlag.get()) {
                // Do some work, but remember to check flag often!
            }
        }
        catch (InterruptedException e) {  
            // Interrupted, no need to check flag, just exit
            return;
        }
    }
}

Upvotes: 1

Related Questions