2016-11-06 61 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更好。 –