Search code examples
javamultithreadinglistthread-safetysynchronizedcollection

Why Java keeps List values for each request even using concurrent list?


In the following methods, I have a list to keep the data and I can populate all the data into this menuDTOList. However, when a send a new request after getting all the data from the first request, the menuDTOList still keeps the data of the first request.

As there are 2 methods recursively calls each other, I cannot make the list to be cleared properly. I tried Collections.synchronizedList() for thread-safety, but it does not make any sense. Also tried to clear the list at different steps, but due to recursive method calls, it did not work correctly.

So, how can I clear the list values on each request while keeping them recursive calls between methodA and methodB?

public class Demo {

    // private List<MenuDTO> menuDTOList  = new ArrayList<>();
    List<MenuDTO> menuDTOList = 
        Collections.synchronizedList(new ArrayList<MenuDTO>());

    protected Iterable<MenuDTO> getData() {
        for (...) {
            methodA();
        }
                
        return menuDTOList;
    }

    private void methodA(final MenuItemExpandedDTO menuItemExpandedDTO) {
            
        menuDTOList.add(dto);

        for (...) {
            methodB();
        }
    }

    private void methodB() {
        for (...) {
            methodA(dto);
        }
    }
}

Solution

  • If you do:

    public class Demo {
    
        protected Iterable<MenuDTO> getData() {
            List<MenuDTO> menuDTOList = new ArrayList<>();
            for (...) {
                methodA(menuDTOList);
            }
                    
            return menuDTOList;
        }
    
        private void methodA(final MenuItemExpandedDTO menuItemExpandedDTO, final List<MenuDTO> menuDTOList) {
                
            menuDTOList.add(dto);
    
            for (...) {
                methodB(menuDTOList);
            }
        }
    
        private void methodB(List<MenuDTO> menuDTOList) {
            for (...) {
                methodA(dto, menuDTOList);
            }
        }
    }
    

    Then each list instance is only used by a single thread, and the list will be available to be garbage collected as soon as the caller of getData discards the reference.