Search code examples
javamultithreadingstaticconcurrentmodification

Avoid global modification of static object when a thread is in particulare block


I have two class, First class(ClassServletA.java) is the HttpServlet which stores the ipaddress and access time in the HashMap, I want to back up the HashMap in DB on daily basis, So I am Scheduling the task and storing the static HashMap object in DB and then reinitialize HashMap (after storing in DB) .

Is it possible to Lock the static Object Globally ?

 public class ClassServletA {
  public static  Map<String,String> myMap = new HashMap<String, String>();

   void doGet(HttpServeltRequest request , HttpServletResponse response){
    myMap.put("ipaddress", "accessTime");
   }
}

Second Class is the scheduler:

public class MyDailyTask implements Job {
  void executeMethod(){
  //Writing the map object to file or database login here
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ObjectOutputStream out = new ObjectOutputStream(bos);
    out.writeObject(ClassServletA.myMap);
    out.flush();
    out.close();
    // Reinitialize the hashmap 
    ClassServletA.myMap=new HashMap<String,String> ();
    }
}

Is it possible to lock OR avoid the modification of the ClassServletA.myMap Map object globally within scheduling time period when the scheduler ( MyDailyTask.java) executes the executeMethod().


Solution

  • In case you just want to make sure that myMap is not modified while performing executeMethod but you don't want to block access to it for other threads you could use an AtomicReference

      public class ClassServletA {
      public static final AtomicReference<Map<String,String>> myMap = new AtomicReference(new HashMap<>());
    
       void doGet(HttpServeltRequest request , HttpServletResponse response){
        myMap.get().put("ipaddress", "accessTime");
       }
    }
    
    public class MyDailyTask implements Job {
      void executeMethod(){
      //Writing the map object to file or database login here
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream out = new ObjectOutputStream(bos);
        out.writeObject(ClassServletA.myMap.getAndSet(new HashMap<>()));
        out.flush();
        out.close();
        }
    }
    

    In case you want to block any access to myMap, consider using a ReadWriteLock. See other SO questions about it: Java Concurrency: ReadWriteLock on Variable

    Either way, a HashMap is not thread safe and requires proper synchronization for concurrent access. See Java Multithread Access Static Variable