下面是我目前正在建設一個Web服務器的一個片段:奇特行爲多線程/ volatile變量/條件句/環路(JAVA)
// ...
threadPool = Executors.newCachedThreadPool(); while (true) if(this.isOn) { try { // listen for incoming connection this.clientSocket = serverSocket.accept(); } catch (IOException e) { System.err.println("LOG: >> Accept failed! "); System.exit(1); } // as soon as a connection is established send the socket // with a handler/processor to the thread pool for execution threadPool.execute(new ClientRequestProcessor(clientSocket)); }
// ...
請注意,isOn變量是一個VOLATILE布爾值。
如果我把這個if變成了一段時間......這段代碼有效......但事實並非如此。請問爲什麼?從邏輯的角度來看,兩者都應該工作,即使我在一個if中測試該標誌......我是否錯過了某些東西?!
[稍後編輯:]不工作我的意思是...一個瀏覽器(例如firefox)無法連接,實際上它不斷嘗試但最終超時。再一次,如果我改變,如果(isOn)變成一段時間(isOn),它就像一個魅力。
任何建議/想法都非常歡迎!
P.S.我需要這個組合「while(true)if/while(test flag){...}」,因爲服務器可以從GUI啓動/停止......所以最高級別while(true)是需要的,所以我可以重新檢查我是否在(並因此監聽連接)或者我是否關閉(並且不關心傳入連接)。針對GUI的事件處理程序可以隨時修改標誌。
我完全同意你所說的話。另外,將標誌更改爲false仍然可以保證在服務器實際「停止服務」之前另一個「正在監聽連接」。但是,這仍然不能解釋我使用當前版本的代碼時出現的不規則行爲!我可能會採用你的解決方案,但我仍然很好奇爲什麼一個版本可以工作,而另一個不是......當邏輯上都應該。問題並不是真的如果有更好的解決方案(你已經證明存在!),而是爲什麼這個java代碼行爲如此笨拙...... – Tibbers 2011-01-05 10:00:57
@Tibi,while(true)if(flag)while while(true)而(國旗)在你的情況下應該是相同的。我懷疑你的測試不穩定可重現。 – 2011-01-05 13:40:46
再說一次,你也可以在這一個上。因爲如果我使用調試器運行if-variant並逐行執行代碼,那麼它完美工作......但是,如果我只是運行並保持獨立,if-variant不起作用!所以,實際上我可能無法重現機器的實際狀態,因此任何試圖理解這種尷尬行爲的嘗試都是徒勞的。無論哪種方式,感謝您的及時迴應......您的(初始)重構/重新設計主張已經實施並且像魅力一樣起作用! – Tibbers 2011-01-07 09:48:14