我正在使用java.net.Authenticator創建阻塞對話框,該對話框在用戶第一次通過代理建立任何連接時請求代理登錄名/密碼。 Authenticator工作得很好,但當我嘗試同步顯示輸入對話框的方法時,我遇到了一些奇怪的問題。事件調度線程內部同步問題
這裏的問題是我發現的一個抽象的工作代碼示例:
private static JFrame frame;
public static void main (String[] args)
{
frame = new JFrame ("Frame");
frame.add (new JLabel ("This is main application"));
frame.setSize (500, 500);
frame.setLocationRelativeTo (null);
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
frame.setVisible (true);
// Cycling thread
new Thread (new Runnable()
{
public void run()
{
while (true)
{
// Opening new dialog in a separate event dispatch thread
SwingUtilities.invokeLater (new Runnable()
{
public void run()
{
showSomeLockingDialog();
}
});
// Wait 3 seconds before next window
try
{
Thread.sleep (3000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}).start();
}
private static final Object lock = new Object();
private static void showSomeLockingDialog()
{
synchronized (lock)
{
// Output to see that this method is not finished yet
System.out.println ("Method start");
// Modal thread-blocking dialog
JDialog dialog = new JDialog (frame, "Lock");
dialog.add (new JLabel ("This should be blocking other dialogs"));
dialog.pack();
dialog.setLocationRelativeTo (null);
dialog.setModal (true);
dialog.setVisible (true);
// Output to see that this method is not finished yet
System.out.println ("Method end");
}
}
所以基本上:
- 有一個明顯的主框架(實際上,只是爲了讓JVM運行)
- 有循環線程請求每個週期中的showSomeLockingDialog()方法
- 方法在「鎖定」對象上同步
- 有一個在方法控制檯輸出開始和結束
所以,如果你運行這個例子,你會看到,每個週期的新對話框彈出忽略同步,即使您不關閉先前的對話框。我也嘗試了簡單的方法同步,但它具有相同的效果。如果我們改變我們稱之爲showSomeLockingDialog方式
一切都在變化()位:
new Thread (new Runnable()
{
public void run()
{
showSomeLockingDialog();
}
}).start();
(只使用一個單獨的線程,而不是調用事件調度線程內法)
這樣一切正常我期待它的工作方式 - 新的對話調用被阻止,直到之前調用的那個被關閉。
而這很奇怪 - 事件調度線程的特殊之處在於同步被忽略了嗎?
或者如果它實際上是一個錯誤 - 是否有任何解決方法? 也許我失去了一些東西......巨大
的幾點思考:在我看來是模態對話框調用setVisible方法充當不同的事件調度線程內(否則它會阻礙整個界面如果從那裏調用)。但如何影響同步...
P.S.不,我不能只在我的具體情況下使用第二個(工作)的例子,因爲我不是在我想要的地方調用該方法 - 它從隨機地點調用,主要來自標準的JDK類(當任何資源從網上下載 - 在JLabel中的圖像,一些URL輸入流或其他任何東西)。
感謝您的文檔鏈接,似乎我對setVisible方法的猜測是正確的。既然我不能離開這個方法(在從對話框中獲取信息之前),也不能用別的東西鎖定它(它的EDT,所以如果我鎖定它 - 只要鎖被激活,接口就會鎖住) - 我只能創建我的自己的同步「邏輯」爲這個具體情況,對嗎? –
你對調度線程是正確的。你應該避免對它進行長時間的操作或阻止它。看起來你需要自己做同步邏輯。 – henryabra
問題是我應該從EDT調用的方法中返回授權令牌。我無法阻止它(意味着我不能再等待早先完成的這種方法的另一個調用),因爲它的EDT和阻止它會凍結整個界面。我甚至無法想象在這種情況下該怎麼做......到目前爲止,我只是在顯示授權對話框時顯示的所有其他調用返回null,而不是顯示多個auth對話框(因此所有其他連接可能會因接收而失敗空令牌)。 –