我更改了文本,因此某些注释可能引用了以前的版本

下面是代码示例。有两个线程:观察者和可观察者。可观察是由主开始的。观察者从可观察对象的创建开始,并以其破坏结束。但这不会发生,并且观察者将永远运行。为什么?

public class ThreadObjectReaping01 {

private static final Logger log = LoggerFactory.getLogger(ThreadObjectReaping01.class);

public static void main(String[] args) throws InterruptedException {

    Thread observable = new Thread("observable") {

        private Thread observable2 = this;

        Thread observer = new Thread("observer") {
            @Override
            public void run() {

                log.info("Observer is starting");

                while(!interrupted()) {

                    if( observable2.isAlive() ) {
                        log.info("Observable is running");
                    }
                    else {
                        log.info("Observable is NOT running");
                    }

                    try {
                        sleep(1000);
                    } catch (InterruptedException e) {
                        interrupt();
                    }
                }

                log.info("Observer is terminating");

            }
        };

        {
            observer.start();
        }

        @Override
        protected void finalize() throws Throwable {
            observer.interrupt();
        }

        @Override
        public void run() {

            log.info("Observable is starting");

            while(!interrupted()) {
                try {
                    sleep(1000);
                } catch (InterruptedException e) {
                    interrupt();
                }
                //log.info("Observable is running");
            }


        }
    };

    log.info("Main is starting observable");
    observable.start();
    Thread.sleep(10000);
    log.info("Main is interrupting observable");
    observable.interrupt();
    observable = null;
    Thread.sleep(10000);
    log.info("Main is terminating");

}
}

最佳答案

当您的主要对象(重写finalize())不再可用(有资格进行垃圾回收)时,GC将首先调用finalize()。我看到您正在跟踪它,因此请确保实际上已调用您的日志记录消息。

但是,仅仅调用interrupt()是不够的,守护程序线程必须主动检查该标志(使用isInterrupted())并正确响应它,并尽快关闭。另外,您应该正确处理InterruptedException(如果有)。

您的线程是守护程序线程这一事实是无关紧要的。非守护程序线程阻止JVM退出(当所有非守护程序线程完成其工作时,JVM就会存在)。在这里,您正在手动中断线程-该线程是否是守护程序都没有关系。



您的"Reporting of..."消息曾经显示吗?您可以在此处放置一个断点。这意味着实现finalize()的对象是GC的受害者。如果只有reporter线程持有对您的主对象的引用(反之亦然),即使没有循环引用,如果外部都未引用这些对象,GC仍将释放这些对象。

也可以看看:

  • How to break an infinite loop
  • Interrupting a thread in Java
  • Stopping a specific java thread
  • Best way to handle exception when joining a thread

  • 圣经后

    与您的问题无关。如果您使用的是slf4j,则:
    log.info(String.format("Reporting of (%s) is about ot interrupt", getName()));
    

    可以替换为:
    log.info("Reporting of {} is about to interrupt", getName());
    

    关于java - 如何配置一对相关的线程对象?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/11674664/

    10-11 23:05
    查看更多