0

I have an Util class that i use for Stats computation. An Exponential moving average is calculated among multiple threads. Also this threads pass differents values some times double and others long. I want to make generics and also be sure that when applying synchronized to the method's signature.

    public class StatUtils {

    public static class WMA {
        // MMA
    }
    public static class EMA {

        /** The alpha. */
        private static double staticAlpha = 0.9;

        /** The old value. */
        private static double staticOldValue = 1.0;

        /**
         * Compute.
         *
         * @param pValue the value
         * @return the double
         */
        public static synchronized double compute(double pValue) {
            if (staticOldValue == 0.0) {
                staticOldValue = pValue;
                return pValue;
            }
            double lValue = staticOldValue + staticAlpha * (pValue - staticOldValue);
            staticOldValue = lValue;
            return lValue;
        }
    }
}

Is the compute method thread safe ? If Yes is that possible to make this static class generic ?

Hassam Abdelillah
  • 2,246
  • 3
  • 16
  • 37
  • Problem seems to be with your class design. Why do you want to instantiate `static` class member `staticAlpha` from constructor? I'm not sure about the exact requirement but looking at your code I think you don't even need synchronization, if designed properly. – justAbit Jul 05 '16 at 08:49
  • Note that was an error i do not instantiate class of course – Hassam Abdelillah Jul 05 '16 at 08:53
  • What part should become generic? If you want to use a generic type instead of doubles, what should 'compute' do? – Boris van Katwijk Jul 05 '16 at 08:53
  • I compute prices in double. In other ones, i compute time periods in long. – Hassam Abdelillah Jul 05 '16 at 08:56
  • It still sounds like 2 different methods unless the code for computing prices in `double` is the same computing time period in `long` – Christopher Z Jul 05 '16 at 10:05

2 Answers2

1

As long as synchronized, your method is thread safe, but you can't make generic a static class. The generic type is resolved when the class is instantiated but this will never occur with a static class.

You could define a generic method like:

public static synchronized <T extends Number> compute(T pValue)

But In your case you can simply use double since a long value can be casted to double without problem.

  • But the opposite have a loss of precision. And in case of time it is very valuable. – Hassam Abdelillah Jul 05 '16 at 10:02
  • 1
    But you dont't need to cast from double to long. Just use double to store the result. For example a timestamp of (long)9223372036854775807 will be stored as (double)9.223372036854776E18. If necessary you can print without scientific notation http://stackoverflow.com/questions/16098046/how-to-print-double-value-without-scientific-notation-using-java. Of course if you work with 19 digits long numbers you will lost the 4 less significant digits when cast from long to double. – Marco A. Hernandez Jul 05 '16 at 10:43
1

Yes, your current approach is thread-safe. But it might not be as efficient as whole compute method will be blocked by a single thread.

I am not sure about EMA algorithm but if you are okay that the threads use almost up-to-date value of staticOldValue then you can improve it like:

  public static class EMA {

    /** The alpha. */
    private static double staticAlpha = 0.9;

    /** The old value. */
    private static double staticOldValue = 1.0;

    private static Object monitor = new Object();

    /**
     * Compute.
     *
     * @param pValue the value
     * @return the double
     */
    public static double compute(double pValue) {
      synchronized (monitor) {
        if (staticOldValue == 0.0) {
          staticOldValue = pValue;
          return pValue;
        }
      }

      double lValue = staticOldValue + staticAlpha * (pValue - staticOldValue);
      synchronized (monitor) {
        staticOldValue = lValue;
      }

      return lValue;
    }
  }
justAbit
  • 4,226
  • 2
  • 19
  • 34