Monday, February 12, 2018

java.util.ConcurrentModificationException of java streaming

Java streaming is a multi-thread process. If more than one thread are modifying the state of the same object, it will throw the java.util.ConcurrentModificationException.

One example is using parallel streaming to delete elements from or inserting elements into the original list/array, which interferes the iterating process of each other. Below is a piece of code of another example.

public class EmployeeState {
      private String name = "";
      private String title = "";
      private int skillLever = 0;

      public void setEmployeeState(String n, String t, int s) {
            name = n;
            title = t;
            skillLevel = s;
      }

      public String getName() { return name; }
   
      public String getTitle() { return title; }

      public int getSkillLevel() { return skillLevel; }
}

Public class EmployeesWithTheSkillLevel {
      private int skillNeeded = 0;
      private List<String> empNames;
      private EmployeeState empState;

      public EmployeesWithTheSkillLevel (int s, List<String> en) {
            skillNeeded = s;
            empNames = en;
            empState = new EmployeeState();
      }

      public boolean filtEmp(String empname) {
            boolean bn = false;
            int skill;
            try ( PreparedStatement ps = getConnection().prepareStatement("select title, skillLevel from employee where name = '"+empname +"'");
                        ResultSet rs = ps.executeQuery()) {

                   if (rs.next()) {
                          skill = rs.getInt("skillLevel");
                          if (skill == skillNeeded) {
                                bn = true;
                                empState.setEmployeeState(empname, rs.getString("title"), skill);
                           }
                    } 
              }
              return bn;
      }

      public void print(String empname){
            System.out.println(empname + "\t\t\t" + empState.getTitle());
      }

      public void printEmp() {
            empNames.parallelStream()
                               //This line will throw the java.util.ConcurrentModificationException
                              .filter(e -> filtEmp(e))
                              .forEach(e -> print(e));
      }
}

The line of code .filter(e -> filtEmp(e)) will throw the java.util.ConcurrentModificationException because the filtEmp method modifies the state of the EmployeeState object which is shared by all threads.

To fix it:
Make the EmployeeState object a method field of the filtEmp method instead of a class field, and pass it to the print method.

public boolean filtEmp(String empname) {
            EmployeeState empState = new EmployeeState();
            boolean bn = false;
            int skill;
            try ( PreparedStatement ps = getConnection().prepareStatement("select title, skillLevel from employee where name = '"+empname +"'");
                        ResultSet rs = ps.executeQuery()) {

                   if (rs.next()) {
                          skill = rs.getInt("skillLevel");
                          if (skill == skillNeeded) {
                                bn = true;
                                empState.setEmployeeState(empname, rs.getString("title"), skill);
                           }
                    } 
              }
              return bn;
      }

      public void print(String empname, EmployeeState empState){
            System.out.println(empname + "\t\t\t" + empState.getTitle());
      }

Or you can synchronize the block of code that changes the shared EmployeeState object.

public boolean filtEmp(String empname) {
            boolean bn = false;
            int skill;
            try ( PreparedStatement ps = getConnection().prepareStatement("select title, skillLevel from employee where name = '"+empname +"'");
                        ResultSet rs = ps.executeQuery()) {

                    synchronized (lock) {
                         if (rs.next()) {
                                skill = rs.getInt("skillLevel");
                                if (skill == skillNeeded) {
                                      bn = true;                           
                                      empState.setEmployeeState(empname, rs.getString("title"), skill);
                                }
                           }
                    } 
              }
              return bn;
      }

-----------------------------------------------------------------------------------------------------------------

                        
If you have ever asked yourself these questions, this is the book for you. What is the meaning of life? Why do people suffer? What is in control of my life? Why is life the way it is? How can I stop suffering and be happy? How can I have a successful life? How can I have a life I like to have? How can I be the person I like to be? How can I be wiser and smarter? How can I have good and harmonious relations with others? Why do people meditate to achieve enlightenment? What is the true meaning of spiritual practice? Why all beings are one? Read the book free here.
     


No comments:

Post a Comment