使用复杂的子例程终止线程.Java语言



和其他许多人一样,我在不使用stop()的情况下杀死线程时遇到了问题。我曾尝试在线程run()例程中使用带有while循环的变量volatile。

据我所见,问题是while循环只在每转之前检查变量。运行的复杂例程Im需要很长时间,因此线程不会立即终止。

我想终止的线程是一个连接到另一台服务器的例程,它使用了很长的时间。我想要一个中止按钮。(终止线程)。我试着用一些代码来解释。

class MyConnectClass{
    Thread conThread;
    volitile boolean threadTerminator = false;
        ..some code with connect and abort button..

    public void actionPerformed(ActionEvent e) {
        String btnName = e.getActionCommand();
        if(btnName.equalsIgnoreCase("terminate")){
            threadTerminator = true;
            conThread.interrupt();
            System.out.println("#INFO# USER ABORTED CURRENT OPERATION!");
        }else if(btnName.equalsIgnoreCase("connectToServer")){
            conThread = new Thread() { 
                public void run() {
                    while(threadTerminator == false){
                        doComplexConnect(); //Uses a loooong time
                    }
                }
            }
            conThread.start();  
        }   
    }
}

如何立即终止我的"连接"线程?谢谢

Java不久前放弃了Threads中的stop()方法,因为不恰当地杀死Thread会在JVM中造成巨大问题。从用于stop()的Javadoc:

使用thread.stop停止线程会使其解锁已锁定的所有监视器(这是未检查的ThreadDeath异常在堆栈中传播的自然结果)。如果这些监视器以前保护的任何对象处于不一致状态,则损坏的对象对其他线程可见,可能导致任意行为。停止的许多用法应该被简单地修改一些变量以指示目标线程应该停止运行的代码所取代。目标线程应该定期检查该变量,如果该变量指示它要停止运行,则以有序的方式从其run方法返回。如果目标线程等待很长时间(例如,在条件变量上),则应该使用中断方法来中断等待。

在大多数情况下,只要可以安全终止,就由您检查threadTerminator变量,并优雅地处理线程退出。看见http://docs.oracle.com/javase/6/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html

如果您正在执行长I/O,您可能会遇到麻烦。某些I/O操作会抛出InterruptedException,在这种情况下,您可以中断线程,并且如果您在该I/O中,该异常或多或少会立即抛出,您可以中止并清理线程。出于这个原因,中断线程比使用特殊的自定义threadTerminator变量更可取——它更标准。在I/O之外的主代码中,定期检查interrupted()或isInterrupted)(而不是threadTerminator==false)。

如果您正在执行不抛出InterruptedException的I/O,有时您可以关闭Socket或类似的操作,并捕获IOException。有时你会陷入困境。

为什么不中断线程并继续前进,让它挂起直到完成?用户可以启动一个不同的操作(线程),而旧的线程优雅地完成(从我所看到的情况来看,你已经在做了)

这样做的缺点是,当用户开始大量(多个线程)单击"connectToServer"时,或者当线程无法终止(挂起的线程)时,您会遇到问题。但也许这对你的目的来说已经足够了?

编辑:
实现一种防止生成新的连续线程的机制很简单,除非"这很好"(例如,使用信号量)。

棘手的部分将是决定打开一个新的连接是否好。你可以询问原始线程(比如有一个isalive()方法),或者你试图连接到的一方。或者你可以寻求一个超时解决方案。例如,如果时间戳在1分钟内没有更新,您可以让conthread更新时间戳,并决定它已经死了。最普遍适用的解决方案可能是超时解决方案。

最新更新