【问题标题】:Visibility in Java global exception handlerJava 全局异常处理程序中的可见性
【发布时间】:2014-10-16 15:13:21
【问题描述】:

我正在用 Java 编写一个程序,它允许人们将数据输入到表单中,作为帮助台的工作。然后使用提交的表单创建一个 helpRequest 对象,该对象被输入到通用队列中以存储在二进制文件中。但是,该项目的责任(这是一项学校作业)是使用异常使程序失效。该程序的一项具体规定是,它必须通过在“优雅地”终止之前尝试保存当前的 helpRequest 队列来处理无法继续的任何情况。我已经在代码中设置了所有这些,但是当处理程序运行时(在我的测试中除以零),程序一旦尝试对 helpQueue 执行任何操作就会挂起。

我尝试查找 Java 全局变量和全局异常处理程序,但似乎没有任何内容可以解决使用来自另一个/抛出类的结构或变量的主题。

这是处理程序的代码。我在抛出类 HelpDeskForm 中将 helpQueue 声明为 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 
    }
}    

【问题讨论】:

  • 最好为HelpDeskFormhelpQueue的实现提供一些代码。
  • '为什么 helpQueue 看起来不可见' -- 是否声明为 volatile?该队列是线程安全的(例如,BlockingQueue)吗?你能做线程转储,看看UncaughtExceptionHandler正在执行什么语句吗?
  • 去掉UI代码还能用吗?
  • ...为什么需要全局异常处理程序?在您实际尝试执行操作的位置,try/catch 块是否存在问题?
  • 您是否将 UncaughtExceptionHandler 注册到您的线程?

标签: java exception-handling global visibility uncaughtexceptionhandler


【解决方案1】:

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 的线程安全性保证了其内容的正确可见性。

【讨论】:

    猜你喜欢
    • 2010-12-05
    • 1970-01-01
    • 1970-01-01
    • 2013-10-25
    • 2014-04-17
    • 2012-12-31
    • 2011-05-19
    • 2011-08-31
    • 1970-01-01
    相关资源
    最近更新 更多