多线程时如何防止GUI相互干扰

时间:2016-11-06 16:54:54

标签: java multithreading swing

我一直是用Java处理图像的程序。然而,在该图像处理期间,同时运行的摆动GUI(并且包括进度条等)简单地冻结直到处理完成。我已经尝试多线程程序来解决这个问题,让处理在后台运行,但它似乎不起作用。

以下是我一直在使用的一些代码。

public class GUIThread implements Runnable {
    public static final int CHOOSER_HUB = 0;
    public static final int LAUNCH_IMAGE_PREVIEWER = 1;
    public static final int DISABLE_PREVIEWER_BUTTONS = 2;
    public static final int MEMORY_USAGE_WINDOW = 3;
    private int guiNumber;

    // ==========================================================================
    // |                               START CODE                               |
    // ==========================================================================

    /**
     * Runs begins the thread. This method is also for pre-run configuration,
     * but so far there is none of that.
     * 
     * @param GUINumber
     *            The GUI number, indicating which GUI to start.
     */
    public void start(int GUINumber) {
        DebugMessenger.out("Starting new thread for GUI");
        guiNumber = GUINumber;
        run();
    }

    /**
     * Starts the thread, and runs a method determined by what guiNumber was set.
     */
    @Override
    public void run() {
        DebugMessenger.out("Thread running");
        if (guiNumber == GUIThread.CHOOSER_HUB)
            createChooserHub();
        if (guiNumber == GUIThread.LAUNCH_IMAGE_PREVIEWER)
            createPreviewer();
        if (guiNumber == GUIThread.DISABLE_PREVIEWER_BUTTONS)
            disablePreviewerButtons();
        if (guiNumber == GUIThread.MEMORY_USAGE_WINDOW)
            createMemoryUsageWindow();
    }

    /* More code, including methods called by run() */

}

要启动我的程序,我只需运行以下代码。

public class Main {
    /**
     * Main method. Starts the threads and lets them roll.
     * @param args
     */
    public static void main(String[] args) {
        // start threads
        DebugMessenger.out("Starting Main");
        GUIThread guiThread = new GUIThread();
        guiThread.start(GUIThread.LAUNCH_IMAGE_PREVIEWER);
        if(Config.DEBUG_OUTPUT_ENABLED) {
            memBarThread = new GUIThread();
            memBarThread.start(GUIThread.MEMORY_USAGE_WINDOW);
        }
        DebugMessenger.out("Main complete");
    }
}

正如您所看到的,我使多线程尽可能简单,但似乎当我运行程序并且图像预览器开始处理时,内存使用窗口会冻结。我该如何防止这种情况?

3 个答案:

答案 0 :(得分:0)

您在代码中遗漏的一个重要问题是,在Java中,您永远不会自己调用run()(如果您这样做,它将不会创建单独的线程,而不是它将在主线程中运行),而是你将创建一个Thread对象并启动Thread(使用如下所示的start方法),以便它将调用{{1单个线程中的()方法,如下所示:

GUIThread类:

run

主要类别:

public class GUIThread implements Runnable {
    public static final int CHOOSER_HUB = 0;
    public static final int LAUNCH_IMAGE_PREVIEWER = 1;
    public static final int DISABLE_PREVIEWER_BUTTONS = 2;
    public static final int MEMORY_USAGE_WINDOW = 3;
    private int guiNumber;


    public void setGUINumber(int GUINumber) {
        this.guiNumber = GUINumber;
    }

    @Override
    public void run() {
        DebugMessenger.out("Thread running");
        if (guiNumber == GUIThread.CHOOSER_HUB)
            createChooserHub();
        if (guiNumber == GUIThread.LAUNCH_IMAGE_PREVIEWER)
            createPreviewer();
        if (guiNumber == GUIThread.DISABLE_PREVIEWER_BUTTONS)
            disablePreviewerButtons();
        if (guiNumber == GUIThread.MEMORY_USAGE_WINDOW)
            createMemoryUsageWindow();
    }

    /* More code, including methods called by run() */

}

您可以查看here

答案 1 :(得分:0)

您根本没有使用多线程来使用您提供的代码。

首先调用GUIThread.start(int),无论输入此调用run(),我猜这是阻塞工作的方法。无处创建新线程并告知它开始独立执行。

我建议您研究以下概念:

答案 2 :(得分:0)

您的GUI冻结,因为操作仍在Swing GUI线程中运行。

让GUIThread类扩展Thread(而不是实现Runnable)并调用Thread的start方法。