为什么 Java 即使使用并发列表也会为每个请求保留列表值?

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

在下面的方法中,我有一个列表来保存数据,我可以将所有数据填充到这个 menuDTOList 中。但是,当从第一个请求获取所有数据后发送新请求时,menuDTOList 仍然保留第一个请求的数据。

由于有2个方法相互递归调用,我无法正确清除列表。我用 Collections.synchronizedList()thread-safety,但没有任何意义。也尝试过在不同的步骤中清除列表,但由于递归方法调用,它没有正常工作。

那么,如何清除每个请求的列表值,同时保持它们在 methodAmethodB 之间进行递归调用?

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

能否请您补充更多细节,for 循环的条件是什么?

在当前状态下,我在这里看到 2 个不同的问题。

  1. methodA和methodB互相调用,好像是死循环问题
  2. 此外,如果您想让列表对于设置器来说只是线程安全的,您可以创建一个普通的易变列表。类似 volatile List<MenuDTO> menuDTOList = new ArrayList<>() 的东西,或者如果您正在寻找开箱即用的数据结构,您可以使用 ConcurrentLinkedQueue。或者最重要的是,提供列表作为方法参数并完全避免 class 级别变量

如果你这样做:

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

然后每个列表实例仅由单个线程使用,一旦 getData 的调用者丢弃引用,列表将可用于垃圾收集。