我有一個擴展JDialog的登錄表單,用戶可以通過刷卡或通過輸入用戶名和密碼進行登錄。從事件派發線程(EventQueue)停止另一個線程
我創建了一個Runnable
守護進程,它與磁條閱讀器進行通信,當它啓動時,它將請求刷卡並等待,直到刷卡。如果應用程序需要取消請求以執行其他操作,那麼它將產生該線程將捕獲的事件,從而取消等待刷卡的請求。
當用戶刷卡時,應用程序將讀取用戶ID的軌跡並驗證它,如果驗證成功,停止命令將被髮送到卡刷卡守護進程並停止線程。
當用戶輸入用戶名和密碼時,swing程序包將訪問響應登錄按鈕的單擊事件的線程(AWT-EventQueue-0)並繼續評估登錄憑證。
我的問題是,每當應用程序在這個AWT-EventQueue-0線程上,向卡刷卡守護進程發送停止事件將不起作用,守護進程將停留在線程堆棧上。
編輯1:停止命令在刷卡登錄時工作得很好。它優雅地結束了刷卡線程。在這種情況下,當前線程作用域位於CardSwipeThread上。
問題發生在手動登錄時,當用戶單擊登錄按鈕時,當前有效範圍的線程將是AWT-EventQueue-0或Event Dispatch Thread。將CardSwipeThread的volatile布爾值更新爲false不會阻止其運行。
編輯2:讀卡器與應用程序通信的唯一時間是刷卡時,手動登錄時發生問題,不需要刷卡。因此,CardSwipeThread沒有問題,因爲IO操作被阻止而無法正常結束。原來,有一個隱藏在灌木叢後面。
這是我的代碼的一部分:
LoginDialog.java
public class LoginDialog extends JDialog implements ActionListener, WindowListener
{
public LoginDialog()
{
super();
// ..More code that instantiates the objects of this JDialog.
SwipeReader.getInstance().enable(true);
}
class SymAction implements java.awt.event.ActionListener
{
public void actionPerformed(java.awt.event.ActionEvent event)
{
Object object = event.getSource();
if (object == logonButton)
{
logonButton_actionPerformed(event);
}
// ..More conditions for other objects.
}
}
// The keyboard login method, does not terminate the card swipe daemon thread.
void logonButton_actionPerformed(java.awt.event.ActionEvent event)
{
try
{
// ..More code that will evaluate login information.
if (authenticate == -1)
{
// Notify for failed login.
}
else if (authenticate == 0)
{
SwipeReader.getInstance().enable(false);
}
}
catch (Exception e)
{
// Error logger.
}
}
// The card swipe listener used for card login.
public void deviceDataReceived(Object object)
{
try
{
// ..More code that will evaluate login information.
if (authenticate == -1)
{
// Notify for failed login.
}
if (authenticate == 0)
{
SwipeReader.getInstance().enable(false);
}
}
catch (Exception e)
{
// Error logger.
}
}
}
SwipeReader.java
public class SwipeReader
{
// This is a singleton class that creates the thread for the daemon.
CardSwipeDaemon cardSwipeDaemon;
Thread cardSwipeThread;
SwipeReader instance;
private SwipeReader() {}
public static SwipeReader getInstance()
{
if (instance == null) { instance = new SwipeReader(); }
return instance;
}
public void enable (boolean isEnabled)
{
if (isEnabled)
{
cardSwipeDaemon = new CardSwipeDaemon();
cardSwipeThread = new Thread(cardSwipeDaemon, "CardSwipeThread");
cardSwipeThread.start();
}
else
{
cardSwipeDaemon.stop();
cardSwipeThread = null;
}
}
}
CardSwipeDaemon.java
public class CardSwipeDaemon implements Runnable
{
CardSwipeDaemon instance;
private static volatile boolean listenforswipe = true;
public CardSwipeDaemon() {}
public static synchronized CardSwipeDaemon getInstance()
{
if (instance == null) { instance = new CardSwipeDaemon(); }
return instance;
}
public run()
{
listenforswipe = true;
while (listenforswipe)
{
// Code for reading the magnetic stripe data.
}
}
public void stop()
{
listenforswipe = false;
}
}
一次只能運行CardSwipeReader的一個實例,SwipeReader.java的目的是創建CardSwipeReader的新實例(如果它爲null或僅返回存在的實例)。我沒有包含讀取磁條數據的代碼,因爲我認爲它與我的問題無關,而且我只需要關閉CardSwipeThread。我需要停止CardSwipeThread,因爲讀者不僅可以用於登錄,還可以進一步將信用付款用於應用程序。我在我的問題中添加了更多信息。 – ELM
@ELM **顯然,您在CardSwipeReader中阻止了IO,導致無法完成** –
@ELM:讀卡器API可能允許規定超時,以減輕此風險。 – trashgod