2

我正在用Java編寫一個程序,它允許一個人將數據作爲幫助臺的作業輸入到表單中。提交的表單然後用於創建一個helpRequest對象,該對象被輸入到一個通用隊列中以存儲在二進制文件中。然而,項目的責任(這是一項學校任務)是使用異常使程序失敗。該程序的一個具體規定是,它必須處理任何在「優雅地」終止之前嘗試保存當前helpRequest隊列無法繼續的情況。我已經在代碼中設置了所有這些,但是當處理程序運行時(在我的測試中通過零除),程序一旦嘗試使用helpQueue執行任何操作就會掛起。在Java全局異常處理程序中的可見性

我試過查找Java全局變量和全局異常處理程序,但似乎沒有解決從另一個/拋出類使用結構或變量的主題。

這裏是處理程序的代碼。我將helpQueue聲明爲throwing類HelpDeskForm中的public和static,並且NetBeans接受我在此處提供的所有代碼。引發的異常發生在隊列處理後。

public class GlobalExceptionHandler implements Thread.UncaughtExceptionHandler { 

    BinaryOutputFile emergencyOutput; 

    public void uncaughtException(Thread t, Throwable e) { 
     Frame f = new Frame(); 
     JOptionPane.showMessageDialog(f, "Program error. Please select a file for queue output."); 
     emergencyOutput = new BinaryOutputFile(); 
     while(!HelpDeskForm.helpQueue.isEmpty()) 
      emergencyOutput.writeObject(HelpDeskForm.helpQueue.remove()); 
     emergencyOutput.close();   
     System.exit(1); 
    } 

} 

而不是具體的解決我的問題,我會很感激,如果有人可以解釋爲什麼helpQueue似乎是不實際可見/可用在這個異常處理程序,或我在做什麼可怕的錯誤。

編輯:我不想過分複雜我的解釋,但這裏是HelpDeskForm代碼,直到我除以零例外。

public class HelpDeskForm { 

    BinaryDataFile input; 
    BinaryOutputFile output; 
    CheckedForm c; 
    helpRequest r; 
    public static Queue<helpRequest> helpQueue; 
    int inputSize; 

    public HelpDeskForm() { 

     GlobalExceptionHandler h = new GlobalExceptionHandler(); 
     Thread.setDefaultUncaughtExceptionHandler(h); 

     input = new BinaryDataFile(); 
     inputSize = input.readInt(); 
     for(int i = 0; i < inputSize; i++) { 
      helpQueue.add((helpRequest)input.readObject()); 
     } 
     input.close(); 

     int y = 0; 
     int z = 2; 
     z = z/y; 
     ... // GUI code follows 
    } 
}  
+0

最好爲'HelpDeskForm'和'helpQueue'實現提供一些代碼。 – evanwong 2014-10-16 15:28:51

+0

'爲什麼看起來像helpQueue不可見' - 是否聲明爲'volatile'?該隊列是否是線程安全的(例如,'BlockingQueue')?你可以做線程轉儲並查看'UncaughtExceptionHandler'執行什麼語句嗎? – 2014-10-16 15:29:34

+0

如果您刪除UI代碼,它會工作嗎? – 2014-10-16 15:30:12

回答

0

HelpDeskForm似乎缺少正在使用的隊列的初始化,所以NPE是不可避免的。嘗試初始化添加到聲明:

public static Queue<helpRequest> helpQueue = new ArrayBlockingQueue<helpRequest>(100); 

此外,對於張貼的代碼,這將是合乎邏輯的補充volatile關鍵字來排隊聲明:

public static volatile BlockingQueue<helpRequest> helpQueue; 

public void createQueue() { 
    // make sure createQueue() is called at the very beginning of your app, 
    // somewhere in main() 
    helpQueue = new ArrayBlockingQueue... 
} 

這樣,所有其他線程,如果有的話,將請參閱正確的隊列引用,線程安全性BlockingQueue可確保其內容的正確可見性。