簡體   English   中英

如何為這個CPU密集型Java應用程序提供GUI?

[英]How do I give this CPU-intensive Java application a GUI?

我正在用Java編寫一些遺傳算法作為學校作業。 到目前為止,我幾乎堅持做控制台應用程序。 但是我認為UI對這個程序真的很有幫助,所以我想制作一個。 我無法弄清楚如何協調事件驅動的GUI和具有開始和結束的控制台應用程序。

理想情況下,我想要一組用於設置的文本框,然后是一個“開始”按鈕。 一旦你點擊開始,算法將開始運行,GUI將在設定的時間間隔內更新最新的程序狀態。 如果沒有算法凍結GUI,反之亦然,我怎么做到這一點? 我不希望任何一個人等着另一個。

在算法運行時如何讓主循環不凍結GUI? 我假設他們需要在不同的線程中,但我以前從未搞過線程。 這對於這項任務來說似乎過於復雜,這一點必須是司空見慣的。

你正在使用線程。 GUI編程要求線程,在大多數情況下 - 幸運的是,Java的線程API並不太可怕(Python的模型就是它,所以它正在做正確的事情 )。

不過,不要被線程嚇倒 - 我會說,這是中級,但是每個程序員都應該理解。

那里有很多信息會使你容易受到攻擊。 然而,GUI應用程序是一個非常有用的領域。 線程的反對者會讓你相信事件編程模型會在這種情況下幫助你,當真的,它不會。 大多數人說“線程糟糕”提出的解決方案通常比線程化更糟糕。

您可以嘗試將解決方案整合到一個線程中,但這需要您的CPU密集型代碼以可預測的時間間隔向GUI提供。 那解決方案很糟糕。 編輯:由於其他人正在建議這種方法,讓我詳細說明為什么它很糟糕:你不知道,有些東西總是在GUI中更新。 當您將窗口移到頂部然后關閉時,該窗口下的整個區域都將失效,並且代碼必須在您的過程中執行 - 以重繪該部分。 即使您非常快速地更新GUI,這也會提供負面的用戶體驗,因為簡單的GUI操作完全阻止。 有時候鼠標懸停時會突出顯示按鈕。 用戶右鍵單擊。 所有這些都需要CPU時間來實現,如果你的孤獨線程正在咀嚼你的GA,它們就不會發生。 正在執行的GUI代碼不僅僅是您的代碼。

這是一篇關於該主題非常有用的文章

關於該主題的兩個課程是:

  1. 並發
  2. Swing中的並發性

對不起 - 看起來后台任務看起來很簡單明了。 不幸的是,Java Swing GUI線程模型有點復雜。 在這方面已經有了一些改進,但是仍然需要先了解一些線程知識。

如果你有時間,我建議閱讀有關骯臟富客戶端中的線程 - 通過SwingWorker進行無痛線程的章節。

替代文字

如果您不耐煩,只需閱讀SwingWorker上的JavaDoc即可。 如果您真的不耐煩,只需從JavaDoc示例用法中復制life示例的含義即可

當我在大學為我的一個計算機圖形課程編寫光線跟蹤器時,我有一個長期運行的任務,我想在跟蹤器繪圖時定期更新顯示。 我使用了兩個獨立的線程 - 一個線程休眠和更新(比如每500毫秒); 另一個線程執行實際的光線跟蹤。 關鍵是要在一個公共對象上進行同步 - 在我的例子中,訪問我的圖像緩沖區是同步點(一個線程無法在沒有先等待直到另一個線程完成讀取的情況下對圖像緩沖區進行更改)。

對於您的GA處理,您可能會有類似這樣的內容(偽代碼):

假設您有一些對象, generationHistoryObject ,它存儲您要在GUI中顯示的狀態,然后:

(在線程#1中:)

Generation newGeneration = doMutationAndTestThisGeneration(lastGeneration);
synchronized (generationHistoryObject) {
 generationHistoryObject.updateWithNextGeneration(newGeneration);
}

(在線程#2中:)

while (!programIsDone()) {
 synchronized (generationHistoryObject) {
  drawGuiForCurrentState(generationHistoryObject);
 }
 Thread.sleep(500);
}

這個想法是你為每一代孤立地完成耗時的工作,然后更新GUI必須在synchronized塊中訪問的部分(使GUI等待繪制直到更新完成)。

你使用Swing的問題是它是單線程的(這是一件好事)所以你想讓你的工作擺脫Swing線程,這樣你的應用程序就能保持響應。

您需要做的是將您的核心算法轉換為Runnable,因為它可以由SwingWorker和較新的Executors輕松處理(請參閱許多預配置的Executors)。 您還可以創建調查如何將PrintStream創建到JTextPanel,以便您可以使用標准println語句輸出當前狀態信息。

如果要添加停止按鈕,則需要了解線程模型,以便了解如何控制它。 Java Tutorial在這方面有很好的材料以及Swing編程。 強烈推薦。

http://java.sun.com/docs/books/tutorial/uiswing/concurrency/index.html

由於您的應用程序與遺傳算法有關,您可以每一代左右更新GUI。 您可以通過在算法代碼中實現next()方法並從GUI調用它來實現此目的。 這應該很簡單。

但是,如果您真的不希望GUI在等待算法時凍結,那么您應該選擇線程。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM