我正在尝试关闭我的Java应用程序,但线程仍处于打开状态。
当使用默认的Windows x按钮单击关闭时,一切都关闭(可能是由于EXIT_ON_CLOSE?) - 但是当我使用编程按钮时,它会挂起在thread.join()上。
更糟糕的是,窗口处理得很好,因此用户会认为它已关闭 - 但仍有几个AWT线程保持打开状态。我的主线程正在等待ID为20的线程,但我不知道如何获取线程ID。
有人有任何建议吗?
这是我的退出代码:
public synchronized void stop() {
running = false;
frame.dispose();
WindowEvent wev = new WindowEvent(frame, WindowEvent.WINDOW_CLOSING);
Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(wev);
try {
if (server != null) {
server.exit();
}
client.exit();
thread.join();
new Thread(){
public void run() {
System.exit(0);
}
}.start();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
e.printStackTrace();
System.exit(1);
}
}
以下是退出后打开的主题:
这是我的run()
方法的内容:
public void run() {
requestFocus();
while (running) {
getTimer().tick();
if (System.currentTimeMillis() - getTimer().getSecond() > 1000) {
// every second, add a second, print fps and mod title with fps
getTimer().accumulateSecond();
//System.out.println(getTimer().returnFPS());
frame.setTitle(title + " | " + getTimer().returnFPS());
getTimer().resetTick();
ticker++;
}
while (getTimer().getDelta() >= 1) {
// every time delta goes greater than one, update and supertick
update();
getTimer().superTick();
}
if (getTimer().getFPS() > 100) {
try {
Thread.sleep(5);
} catch (Exception e) {
System.err.println("Sleeping failed: " + e);
}
}
render();
if (ticker > 30) {
ticker = 0;
getTimer().hourTick();
}
}
stop();
}
答案 0 :(得分:0)
<强>更新强>
在看到更多代码后,我很确定您的问题是您从一个线程调用stop()
(synchronized
)。在stop()
内,您调用thread.join()
,它会尝试等待thread
实例完成其run()
方法。设置running
标志会导致run()
退出其while
循环,但该方法中的最后一行代码是对stop()
的另一次调用。如果这是您向我们展示的相同 stop()
方法,那么您有一个死锁。
stop()
方法中的run()
调用永远无法进入该方法,因为第一个帖子仍位于stop()
内,正在等待run()
完成(它永远不会,因为它等待能够打电话并输入stop()
)。死锁。
您必须从stop()
内删除对run()
的来电,或者找到另一种方法来修改您的代码。
我不担心识别特定的线程ID。担心让所有线程正常完成。
首先,Thread#join()
不会停止一个帖子。它等待它完成。您正在做的其他事情必须导致/允许thread
实例完成其run()
方法。
我唯一能看到的就是设置
running = false;
您的thread
对象是否在其run()
方法中检查该标志?例如:
public void run() {
while (isRunning()) {
// do some work
Thread.sleep(delay);
}
}
其中isRunning()
会返回running
变量的值吗?
现在,我不能说没有看到更多的代码。但是,您可能选择像这样实施isRunning()
:
public synchronized boolean isRunning() {
return running;
}
如果你这样做,那就有问题了。主线程将以您向我们展示的stop()
方法获取锁定。然后它将进入thread.join()
调用,此时它开始等待工作线程。如果工作线程然后调用在同一个锁上同步的isRunning()
,那么isRunning()
将阻塞,因为锁已经由于主线程在stop()
内而被保持。
如果thread
对象尝试从您向我们展示代码的类中调用任何其他synchronized
方法,则可能会出现同样的基本问题。
长话短说,我们需要看一些代码(在thread
变量表示的线程中运行的代码)。但是,你可能已经陷入僵局。