退出时无法关闭所有AWT线程

时间:2013-05-30 21:48:00

标签: java multithreading join awt exit

我正在尝试关闭我的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);
    }
}

以下是退出后打开的主题:

threads-eclipse

这是我的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();
}

1 个答案:

答案 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变量表示的线程中运行的代码)。但是,你可能已经陷入僵局。

Read more here about stopping a thread gracefully