2011-11-15 62 views
1

我有一個代碼,它使用一個線程來運行多個進度條。Thread.join凍結progressbar

Thread thread1 = new Thread(progressbar1); 
thread1.start(); 
thread2.start() 

等等。我有

thread1.join(); 
thread2.join(); 
thread3.join(); 

但是,凍結所有三個進度欄動畫,並且只在所有線程完成時才顯示完成。 如何解決這個問題? 謝謝。

+0

另請參閱[初始線程](http://download.oracle.com/javase/tutorial/uiswing/concurrency/ initial.html)。 – trashgod

回答

3

Event Dispatch Thread執行任何阻止操作將導致您的GUI無響應並停止重新繪製。這就是爲什麼長時間運行的操作應該在後臺線程中完成的原因。

看起來好像你知道你需要在後臺線程中做些事情,但仍想阻止EDT。你不應該那樣做。相反,你需要一個回調 - 一些後臺線程運行完畢後將運行的代碼。

Java 6+中已提供的回調機制是SwingWorker。實施一名工人,將join()(和start())放入doInBackground()方法中。然後你想要做的任何Swing操作可以在done()中進行。

+0

你能解釋一下你的意思嗎?我不知道你的意思是阻止UI線程。我剛開始學習線程。 –

+0

UI線程(或EDT)是負責處理UI事件(例如鼠標點擊)和重新繪製屏幕的線程。阻塞UI線程僅僅意味着讓它做一些需要很長時間才能完成的事情。例如'join()'使線程等待,直到「加入」線程結束......這可能需要相當長的時間。阻塞造成的危害是在此期間不會處理其他UI事件;即UI變得無響應。 (「很長時間」的長度是主觀的,但當你看到它時你會知道它的。) –

1

您正在阻止UI線程。你不應該那樣做。選項:

  • 另一個線程剛剛呼籲前三join。浪費在創造另一種資源方面,但相當簡單。
  • 使用計數器 - 確保您使用類似AtomicInteger的內容來確保您不會遇到內存模型和競爭條件問題。在3開始計數,並在每個線程結束時遞減當最後一個線程完成其工作(即其遞減將計數器置爲0)時,使得回調到UI中。

(第二子彈可能是你已經在做什麼......這很難說肯定給的只是描述「我用了一個櫃檯。」)

雖然我完全看到你在哪裏」在事件驅動的世界中,來自應用程序的控制流程更難以實現,這就是Swing工作的方式(也是大多數其他UI框架的工作方式)。你只需不能阻塞UI線程。 (這也是爲什麼C#5在語言級別更容易...)

+0

我用一個計數器來跟蹤有多少線程完成了。當所有的線程完成後,我再做一些事情()。但我想在thread1.start()之後的下一行; thread2.start()doSomething()。但進度條全部凍結。 –

+0

@LewsTherin:你需要使用'SwingUtilities.invokeLater'從最後一個線程完成調用'doSomething'。基本上你*不能在UI線程中做任何長時間運行的事情。 –

+0

我會試試看,謝謝。 –