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

Time:11-03

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);
        }
    }
}

CodePudding user response:

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.

CodePudding user response:

Could you please add more details, what is the condition of for loops?

In the current state, I see 2 different problems here.

  1. methodA and methodB are calling each other, seems like the infinite loop problem
  2. Also if you want to make the list just thread-safe for setters, you can create a plain volatile list. Something like volatile List<MenuDTO> menuDTOList = new ArrayList<>() or if you're looking for out of the box data structure, you could use ConcurrentLinkedQueue. Or best of all, provide list as method param and avoid class level variable altogether
  • Related