2016-11-06 119 views
0

我一直是用Java处理图像的程序。然而,在这个图像处理过程中,同时运行的同时(包括进度条等)的swing GUI会冻结,直到处理完成。我试过多线程程序来解决这个问题,让处理在后台运行,但它似乎不工作。如何防止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"); 
    } 
} 

正如你所看到的,我做了关于尽可能简单的多线程,但它似乎仍然是,当我运行程序和图像预览开始处理,内存使用率窗口冻结。我怎样才能防止这一点?

回答

0

你的代码中缺少一个重要的东西,它将成为瓶颈,在Java中,你从来不会自己调用run()(如果你这样做,它不会创建一个单独的线程,而是运行在主线程本身),而将创建一个Thread对象,并开始如低于Thread(使用启动方法),这样它会调用在一个单独的线程的run()方法,如下所示:

GUIThread类:

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() */ 

} 

主类:

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. setGUINumber(GUIThread.LAUNCH_IMAGE_PREVIEWER); 

     //Create and Start the Thread now using Thread API 
     Thread threadObj = new Thread(guiThread).start(); 

     if(Config.DEBUG_OUTPUT_ENABLED) { 
      memBarThread = new GUIThread(); 
      memBarThread.start(GUIThread.MEMORY_USAGE_WINDOW); 
     } 
     DebugMessenger.out("Main complete"); 
    } 
} 

可以here

0

您没有使用多线程在所有与您所提供的代码看起来。

您从调用GUIThread.start(int)开始,不管这个调用run()这是什么输入,我猜是阻塞工作的方法。没有一个新的线程被创建并被告知开始独立执行。

我建议你考虑以下概念:

0

你的GUI冻结因为这些操作仍在Swing GUI线程中运行。

让GUIThread类扩展Thread(而不是执行Runnable)并调用线程的start方法。

+1

工作就像一个魅力!将第一行更改为'public class GUIThread extends Thread {',将'start()'方法重命名为'startThread()',并用'start()'替换'run()'。 – user119567

+0

@ user119567:我很乐意帮助你。 – fireandfuel

+1

您可以使用Runnable启动线程。实现Runnable比扩展Thread更好。 –