为对象定义线程 ID 并中断

Defining a thread id to a object and interrupt

我在系统上有专供用户使用的线程,我希望能够单独停止它们,我是否在创建时将线程 ID 与用户数据一起存储,然后调用中断?或者我可以以某种方式将线程添加到我的用户对象中,然后像 myuser.mythread.interrupt(); 一样调用它,或者这是魔法?

目前我可以停止它们并在没有我想要的线程的情况下重新启动。 但这是一项耗时的任务,还会引发用户必须等待的延迟。

更新,这可以作为答案吗?

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

更新

我设法找到了使用 myuser.mythread.interrupt() 的方法; 或者有点..

我将线程作为子 class 添加到用户 class 并在用户 class 中创建了一个方法来启动和中断,现在我可以启动和停止线程

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

无需创建引用并跟踪除用户对象以外的任何其他内容。

更新(关于接受的答案,使用id作为参考我可以这样做)

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;
        }
    }
}

您可以只存储 Thread 引用,也许在 WeakReference 中,这样如果线程自行退出,线程就会消失。

但是您也可以让线程时不时地检查一个 AtomicBoolean(或 volatile 布尔值)以查看它是否被中断,这样您就不需要对线程的引用。

请注意,如果没有您要停止的线程的合作,停止 Java 中的线程是不可能的。使用 interrupt 或它检查的布尔值并不重要,在这两种情况下,都由线程检查这些标志(interrupt 只是设置一个标志)然后执行一些操作,例如退出。

更新 示例可中断线程 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;
        }
    }
}

最好的方法是保存 Thread 引用并使其可供需要中断它的代码使用。

(对于非沙盒应用程序)遍历所有 JVM 现有线程的树来测试每个线程在技术上是可能的。然而,这很昂贵并且无法扩展。如果您可以存储或传递线程的 ID,那么您应该能够存储或传递 Thread 引用。

在技术上也可以创建您自己的 WeakHashMap<Long, Thread> 并使用它来将线程 ID 映射到线程。但同样的论点也适用....

你问这是不是解决方案:

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

不,不是。或者更准确地说,它只会在线程中断自身的情况下 "work" 。在其他情况下,目标线程不会被中断。


根据您的用例,另一种方法是使用 ExecutionService 而不是裸线程。 submit 方法 return 代表提交任务的 Future 对象。该对象有一个 cancel(...) 方法,可用于在任务运行之前或通过中断 运行 线程来取消任务。