如何从监视器线程中断另一个线程

发布于 2024-09-12 13:55:55 字数 385 浏览 4 评论 0原文

我知道这是不明智的,但我仍然试图研究一种从另一个保持时间的线程中断挂起线程的方法。

我所做的是: 我在可疑的网络操作即将发生之前启动监视器线程。该线程应该监视自启动以来经过的时间,如果时间超过某个阈值,它就会杀死最初启动它的线程。为了通知这个新线程,哪个线程将被杀死,新线程的对象被传递给要监视的线程的对象。

简而言之,这就是发生的情况:

A创建B,B创建C,B告诉C关于它自己的信息,C保持时间,如果时间到期,C杀死B(我在B的run方法中使用“currentThread()”将详细信息传递给C) “并且我已经确认确实正在传递正确的对象)

现在,问题是,这不起作用,由于某种原因,对 B.interrupt() 的调用正在杀死 C 本身。

[注:大写字母表示线程名称]

I know that this is ill advised but still i am trying to look into a method of interrupting a thread which hangs, from another thread which is keeping time.

What i do is:
I start the monitor thread just before a questionable network operation is about to happen. This thread is supposed to monitor the time elapsed since it was started and if the time exceeds some threshold value, it kills the thread that initially started it. In order to inform this new thread , which thread is to be killed , the object of the new thread , is passed an object of the Thread to be monitored.

In a nutshell, this is what happens :

A creates B , B creates C , B tells C about itself , C keeps time , if time expires C kills B (I pass the details to C after in B's run method using "currentThread()" and I have confirmed that the correct object is indeed being passed)

Now, the problem is that , this , is not working , for some reason , the call to B.interrupt() is killing C itself.

[Note : Uppercase letters denote thread names]

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

赏烟花じ飞满天 2024-09-19 13:55:55

我认为您的代码有问题(除非我没有正确理解您的规范)。下面的代码按预期运行(抱歉,可怕的嵌套结构):

输出是:

C is about to interrupt B
B is interrupted
C is still alive... is B alive yet?false

代码是:

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicReference;


public class Scrap {
    public static void main(String[] args) {
        Thread A = new Thread() {
            @Override
            public void run() {
                Thread B = new Thread() {
                    @Override
                    public void run() {
                        final CountDownLatch latch = new CountDownLatch(1);
                        final AtomicReference<Thread> pointer = new AtomicReference<Thread>();
                        Thread C = new Thread() {
                            @Override
                            public void run() {
                                try {
                                    //wait for B to be ready
                                    latch.await();
                                    Thread.sleep(2000);
                                    System.out.println("C is about to interrupt B");
                                    pointer.get().interrupt();
                                    Thread.sleep(2000);
                                    System.out.println("C is still alive... is B alive yet? " + pointer.get().isAlive());

                                } catch (InterruptedException e) {
                                    System.out.println("C interrupted");
                                    return;
                                }
                            }
                        };//C
                        C.start();
                        latch.countDown();
                        //Not sure how you did it, so just going with this:
                        pointer.set(Thread.currentThread());


                        try {
                            Thread.sleep(5000);
                        } catch (InterruptedException e) {
                            System.out.println("B is interrupted");
                            return;
                        }
                        System.out.println("B survived");

                    }
                };//B
                B.start();
            }
        };
        A.start();
    }
}

我(疯狂)的猜测是线程间可见性。在上面的代码中,我使用原子引用来确保可见性。如果您没有这样做,则您传递给线程 B 的引用(值)的任何字段都可能对 C 不可见。然后,当 C 尝试中断此 Thread 对象时,它会看到 null,并且中断结果为 NullPointerExceptin ,不知何故你没有注意到它?

I think something is wrong with your code (unless I didn't get your spec right). The below code runs as expected (sorry for the horrible nested structure):

Output was:

C is about to interrupt B
B is interrupted
C is still alive... is B alive yet?false

Code was:

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicReference;


public class Scrap {
    public static void main(String[] args) {
        Thread A = new Thread() {
            @Override
            public void run() {
                Thread B = new Thread() {
                    @Override
                    public void run() {
                        final CountDownLatch latch = new CountDownLatch(1);
                        final AtomicReference<Thread> pointer = new AtomicReference<Thread>();
                        Thread C = new Thread() {
                            @Override
                            public void run() {
                                try {
                                    //wait for B to be ready
                                    latch.await();
                                    Thread.sleep(2000);
                                    System.out.println("C is about to interrupt B");
                                    pointer.get().interrupt();
                                    Thread.sleep(2000);
                                    System.out.println("C is still alive... is B alive yet? " + pointer.get().isAlive());

                                } catch (InterruptedException e) {
                                    System.out.println("C interrupted");
                                    return;
                                }
                            }
                        };//C
                        C.start();
                        latch.countDown();
                        //Not sure how you did it, so just going with this:
                        pointer.set(Thread.currentThread());


                        try {
                            Thread.sleep(5000);
                        } catch (InterruptedException e) {
                            System.out.println("B is interrupted");
                            return;
                        }
                        System.out.println("B survived");

                    }
                };//B
                B.start();
            }
        };
        A.start();
    }
}

My (wild) guess would be inter-thread visibility. In the above code, I'm using atomic reference to ensure visibility. In case you did not do that, it is possible that whatever field you passed Thread B's reference ('s value) might have been invisible to C. Then when C tries to interrupt this Thread object, it sees null and the interrupt results in NullPointerExceptin, and somehow you are not noticing it?

末骤雨初歇 2024-09-19 13:55:55

检查调用 B.interrupt() 时是否收到 SecurityException。另外,您确定您的 B.interrupt() 不会简单地返回并且线程 C 成功完成吗?基于 javadocs,看起来线程C调用B.interrupt()会设置线程B的中断状态并完成运行。我认为线程 B 在您的情况下不会遇到任何异常,除非它满足特殊要求(例如,等待监视器、等待 InterruptibleChannel 等)。

Check if you are getting SecurityException when calling B.interrupt(). Also, are you sure that your B.interrupt() does not simply returns and thread C finishes successfully? Based on javadocs, it looks like thread C's call of B.interrupt() will set thread B's interrupt status and finish running. I do not think thread B will get any exception in your case, unless it meets special requirements (like, waiting on monitor, waiting on InterruptibleChannel, etc).

倾`听者〃 2024-09-19 13:55:55

另一种可能是,C中断成功并返回,但B没有响应。这是很有可能的,因为只有当 B 被相应编码时,中断才有效。

有两种方式对中断做出反应。
1.检查中断标志(通常在需要长时间的操作之前)

if(Thread.currentThread().isInterrupted()){
    log.info("Cancel requested");
    return;
}
someStuffThatTakesLongTimeToExecute();

2.对中断异常采取行动

catch(InterruptedException e){
    log.info("Cancel Requested");

    //Preserve interrupted status.
    //If this class is the owner of the thread,
    //Not necessary.
    Thread.currentThread().interrupt(); 

    return;
}

Another possibility is that, C interrupts successfully and returns, but B does not respond to that. This is quite possible because interruption has only effect if B is coded accordingly.

There are 2 way to react to interruption.
1. Check interruption flag (typically before operations that take long)

if(Thread.currentThread().isInterrupted()){
    log.info("Cancel requested");
    return;
}
someStuffThatTakesLongTimeToExecute();

2.Act on interruption exception

catch(InterruptedException e){
    log.info("Cancel Requested");

    //Preserve interrupted status.
    //If this class is the owner of the thread,
    //Not necessary.
    Thread.currentThread().interrupt(); 

    return;
}
秋日私语 2024-09-19 13:55:55

如果你问我的话,这实际上是正常行为。如果你中断B,它将被垃圾收集。由于对 C 的唯一引用也会被 GC 回收,因此它将不再存在/运行。

最好的想法可能是确保有一个线程管理线程 B 和 C(并将线程 C 注入线程 B)。这样,总是有对线程 C 的引用,并且它可以杀死线程 B。(但您必须小心在管理线程中对线程 B 执行的操作)

This is actually normal behaviour if you ask me. If you interrupt B, it will be garbage collected. Since the only reference to C is then also GC'd, it will cease to exist/run.

The best idea may be to make sure that there is a thread that manages thread B and C (and injects thread C into thread B). That way, there is always a reference to thread C and it can kill of thread B. (but you have to be careful what you do with thread B in the management thread)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文