Java 带侦听器的Singleton与Join

Java 带侦听器的Singleton与Join,java,android,multithreading,Java,Android,Multithreading,我从以前的开发人员(lol)那里继承了这段代码。我正在考虑将其更改为支持连接,而不是使用侦听器类型的回调 我的要求: 1.我需要让调用线程等待DoMath类线程完成。 2.我需要阻止其他线程调用它 在另一个线程(和类)中: 当它调用以下命令时,它当然不会等待或睡眠: public class DoMath { protected math calc() { } public static DoMath getInstance() { if(_instan

我从以前的开发人员(lol)那里继承了这段代码。我正在考虑将其更改为支持连接,而不是使用侦听器类型的回调

我的要求: 1.我需要让调用线程等待DoMath类线程完成。 2.我需要阻止其他线程调用它

在另一个线程(和类)中:

当它调用以下命令时,它当然不会等待或睡眠:

public class DoMath {
    protected math calc() {
    }

    public static DoMath getInstance() {
        if(_instance == null) {
            _instance = new DoMath();
        }

        return _instance;
    }

    // perform a synchronous math calc, and return a boolean indicating success or failure.
    public boolean performMathCalc() {
        MathEngine.setApplicationMode(MathEngine.AUTO);
        MathEngine.getInstance().StartMathCalc(MathEngine.DIVISION);
        return true;
    }

    // perform an async math calc, and call back the listener when done
    public void performMathCalc(final listener client) {
        Thread mathThread = new Thread(new Runnable() {
            public void run() {
                boolean result = performMathCalc();
                client.mathFinished(result);
            }
        });
        mathThread.setDaemon(true);
        mathThread.start();
    }

    public static interface listener {
        public void mathFinished(boolean success);
    }

    protected static DoMath _instance;
}
那么,只使用侦听器还是在调用类中实现连接更好

我需要让调用线程等待DoMath类线程完成

你已经有这个了。请注意有两种
performMathCalc
方法:

  • 第一个方法不接受任何参数,在调用线程上执行计算,然后返回结果。这满足了您的第一个要求

  • 第二种方法是第一种方法的异步包装器;它允许调用者开始计算,然后开始做其他事情,并理解在将来的某个时候,将通知某人操作已完成。这是很有用的功能,所以我会保留它

  • 但是,我确实看到了异步包装的一个问题:如果core
    performMathCalc()
    方法抛出异常,监听器将不会得到通知。考虑使用<代码>尝试/捕获/最后< /Cord>块,以确保侦听器总是得到通知,即使发生错误。您需要决定是向侦听器添加第二个回调(例如,
    mathFailed
    ),还是在出现错误时直接调用
    mathFinished(false)

    我需要阻止其他线程调用它

    我们可以很容易地完成这一点,而且由于异步版本只是委托给同步版本,所以我们只需要锁定同步版本。最简单的方法是将该方法标记为
    synchronized
    ,因为您的类只提供一个逻辑函数:

    public synchronized boolean performMathCalc() {
        MathEngine.setApplicationMode(MathEngine.AUTO);
        MathEngine.getInstance().StartMathCalc(MathEngine.DIVISION);
        return true;
    }
    
    或者,如果最终扩展了
    DoMath
    类以执行其他类型的互不排斥的操作,则可以对特定于操作的锁进行同步

    这就给我们留下了您的单例存取器:

    public static DoMath getInstance() {
        if (_instance == null) {
            _instance = new DoMath();
        }
        return _instance;
    }
    
    此条件初始化不是线程安全的。您的单例非常简单,没有任何预先初始化成本,因此只需将
    \u instance
    标记为
    final static
    ,并在声明中初始化它

    我需要让调用线程等待DoMath类线程完成

    你已经有这个了。请注意有两种
    performMathCalc
    方法:

  • 第一个方法不接受任何参数,在调用线程上执行计算,然后返回结果。这满足了您的第一个要求

  • 第二种方法是第一种方法的异步包装器;它允许调用者开始计算,然后开始做其他事情,并理解在将来的某个时候,将通知某人操作已完成。这是很有用的功能,所以我会保留它

  • 但是,我确实看到了异步包装的一个问题:如果core
    performMathCalc()
    方法抛出异常,监听器将不会得到通知。考虑使用<代码>尝试/捕获/最后< /Cord>块,以确保侦听器总是得到通知,即使发生错误。您需要决定是向侦听器添加第二个回调(例如,
    mathFailed
    ),还是在出现错误时直接调用
    mathFinished(false)

    我需要阻止其他线程调用它

    我们可以很容易地完成这一点,而且由于异步版本只是委托给同步版本,所以我们只需要锁定同步版本。最简单的方法是将该方法标记为
    synchronized
    ,因为您的类只提供一个逻辑函数:

    public synchronized boolean performMathCalc() {
        MathEngine.setApplicationMode(MathEngine.AUTO);
        MathEngine.getInstance().StartMathCalc(MathEngine.DIVISION);
        return true;
    }
    
    或者,如果最终扩展了
    DoMath
    类以执行其他类型的互不排斥的操作,则可以对特定于操作的锁进行同步

    这就给我们留下了您的单例存取器:

    public static DoMath getInstance() {
        if (_instance == null) {
            _instance = new DoMath();
        }
        return _instance;
    }
    
    此条件初始化不是线程安全的。您的单例非常简单,没有任何预先初始化成本,因此只需将
    \u instance
    标记为
    final static
    ,并在声明中初始化它

    我需要让调用线程等待DoMath类线程完成

    你已经有这个了。请注意有两种
    performMathCalc
    方法:

  • 第一个方法不接受任何参数,在调用线程上执行计算,然后返回结果。这满足了您的第一个要求

  • 第二种方法是第一种方法的异步包装器;它允许调用者开始计算,然后开始做其他事情,并理解在将来的某个时候,将通知某人操作已完成。这是很有用的功能,所以我会保留它

  • 但是,我确实看到了异步包装的一个问题:如果core
    performMathCalc()
    方法抛出异常,监听器将不会得到通知。考虑使用<代码>尝试/捕获/最后< /Cord>块,以确保侦听器总是得到通知,即使发生错误。您需要决定是向侦听器添加第二个回调(例如,
    mathFailed
    ),还是在出现错误时直接调用
    mathFinished(false)

    我需要阻止其他线程调用它

    我们可以很容易地实现这一点,而且由于异步版本只是委托给同步版本,我们只需要锁定同步版本
        public class DoMath {
            private Thread mathThread;
    
            protected math calc() {
            }
    
            public static DoMath getInstance() {
                if(_instance == null) {
                    _instance = new DoMath();
                }
    
                return _instance;
            }
    
            // perform a synchronous math calc, and return a boolean indicating success or failure.
            public boolean performMathCalc() {
                if(null != mathThread && mathThread.isAlive())
                     return false;
    
                MathEngine.setApplicationMode(MathEngine.AUTO);
                MathEngine.getInstance().StartMathCalc(MathEngine.DIVISION);
                return true;
            }
    
            // perform an async math calc, and call back the listener when done
            public void performMathCalc(final listener client) {
               //re-start calculation? if so
               if(null != mathThread && mathThread.isAlive()) {
                     matchThread.interrupt();
                     matchThread = null;
                }
    
    
                mathThread = new Thread(new Runnable() {
                    public void run() {
                        boolean result = performMathCalc();
                        client.mathFinished(result);
                    }
                });
                mathThread.setDaemon(true);
                mathThread.start();
            }
    
          public static interface listener {
                public void mathFinished(boolean success);
            }
    
            protected static DoMath _instance;
        }
    
    public static DoMath getInstance() {
        if(_instance == null) {
            _instance = new DoMath();
        }
    
        return _instance;
    }