最近閑時在看《Java多線程設計模式》,很不錯,語言淺顯易懂,而且編排也好,很有啟發性,現在挑其中一章來寫寫心得
worker thread是我們平時用的很多的一種多線程模式,只不過我們常常不把它當模式罷了。基本內容是:有一個流水線(channel),流水線一端有客戶線程client,另一端有工人線程worker,客戶不斷把新的任務(request)放入流水線,工人在另一頭獲得任務,並執行,客戶和工人的數量可多可少,就這麼簡單
這個所謂的pattern初看好像似曾相識,就是一個thread pool嘛, 按通常的做法,request可以實現Runnable介面,把要做的事情放在run方法中,由worker去執行,具體實現時還要注意同步的問題
不過,由此我們可以想到Swing的工作方式。Swing是事件驅動的,它有一個the event-dispatch queue,這裡之所以用the,是因為這個隊列是唯一的,就和上面說的流水線一樣。Swing的各個組件相當於客戶,不斷把各種事件(鍵盤或者滑鼠事件,等等)塞入event queue中,queue有個專門的線程負責把這些事件送給相應的listener,就實現了最基本的事件驅動模型。如果不採用這種模型,即事件由專門線程處理的話,介面的相應速度就很差了
如果有用過Java做遊戲的話,應該都接觸過javax.swing.SwingUtilities這個類,裡面有個invokeAndWait方法,就是用來讓其他線程操作Swing組件的。為什麼不能直接操作呢,如上所述,event dispatch queue是唯一的,因此Swing組件在設計時就沒有過多考慮多線程的問題,反正由event dispatch queue統一操作,這樣可以提高速度(儘管Swing本來就很慢),但是當其他線程要操作Swing組件時,就可能有潛在的不穩定因素,所以才有了invokeAndWait方法,調用此方法的線程會wait直到所需操作已經完成
還沒說完,再仔細想想,我們在程式裡也常常對那些組件直接操作而非用什麼invokeAndWait,這裡又有一些細節值得注意。首先是在你調用組件的setVisible等方法之前,你是可以隨便改組件的,調用完setVisible之後,只有少數方法,比如repaint,addListener等等。最後,根據jdk文檔所言,這個方法是用來給應用程式線程改變GUI外觀的。如果非要直接改,不一定會出錯,多線程本來就是比較難說的,呵呵,我也沒試過,改天可以嘗試一下