Search code examples
javainstance-variables

Non-thread-safe fields should not be static, sonar lint error


hi i have this code sample with me.

 public class Util implements Serializable {


        private static final SimpleDateFormat DATE_KEY_FORMAT = new SimpleDateFormat("yyyyMMdd");
        private static final SimpleDateFormat EUS_WS_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
        private static final SimpleDateFormat DATETIME_KEY_FORMAT = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        public static final String TIME_ZONE_GMT = "GMT";


        /**
         * Returns date in the format yyyyMMdd
         * @return
         */
        public static int getyyyyMMdd() {
            return Integer.parseInt(DATE_KEY_FORMAT.format(new Date()));
        }

        public static int getyyyyMMdd(Date date) {
            return Integer.parseInt(DATE_KEY_FORMAT.format(date));
        }

        public static String getyyMMdd(Date dateTime) {
            return DATE_KEY_FORMAT.format(dateTime);
        }

        public static String getyyyyMMddHHmmssSSSCur(Date dateTime) {
            return DATETIME_KEY_FORMAT.format(dateTime);
        }

if i remove static from line : private static final SimpleDateFormat DATE_KEY_FORMAT = new SimpleDateFormat("yyyyMMdd"), then how to access it in non static manner? because it is showing error in below piece of code :

public static int getyyyyMMdd() {
        return Integer.parseInt(DATE_KEY_FORMAT.format(new Date()));
    }

can any body tell how to access it after removing the static? thanks in advance


Solution

  • Removing the static doesn't make it thread safe: instances can be accessed from separate threads concurrently.

    Consider using a ThreadLocal<SimpleDateFormat>:

    private static final ThreadLocal<SimpleDateFormat> DATE_KEY_FORMAT =
        ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyyMMdd"));
    

    and then access in the static methods like this:

    return Integer.parseInt(DATE_KEY_FORMAT.get().format(new Date()));
    

    Because each thread gets its own instance of SimpleDateFormat, there is no interference between the threads.

    However, mutating changes to the SimpleDateFormat (e.g. setting the time zone) will be persisted in a given thread until you call DATE_KEY_FORMAT.remove(). But if you're never making changes to the instance like that, you don't need to worry about this.