Concurrency causes java object confusion

I. Introduction

        A recent requirement is that users subscribe to the machine information of the store. The data volume is relatively large, and it is put into the thread pool for execution during calculation. It is tested in the pre test that the store machine does not correspond.

Two, investigation

        In fact, it is not a troubleshooting. After looking at this phenomenon and then looking at the code, you will know that the properties of the object are set by different threads. The blogger feels very ashamed. This kind of problem is very low.

         From the code, we can see that because there are too many stores for the user, after setting the store information to chainDTO, it will be put into the thread pool for subsequent business processing, but when the subsequent threads use this object, the main thread is still setting this object and continue to throw it into the thread Pool, so the properties of objects used by child threads are constantly changing.

@Slf4j
@Component
public class ScheduleShopChainImpl extends CommonSubscribeShop implements SubscribeShopFacade<ChainDTO> {

    @Resource
    private MachineQueryService MachineQueryService;

    @Resource
    private SubscribeMachineFacadeFactory<ChainDTO> SubscribeMachineFacadeFactory;

    @Resource
    private ExecutorService subscribeShopExecutorService;
    @Resource
    private Mapper mapper;

    @Override
    public Boolean matching(SubscribeChainEnum factory) {
        return Objects.equals(SubscribeChainEnum.SCHEDULE, factory);
    }

    @Override
    public void process(ChainDTO chainDTO) {
        List<SubscribeShopDTO> SubscribeShopDTOList = super.getBySubscribeId(chainDTO.getSubscribeId());
        if (CollectionUtils.isEmpty(SubscribeShopDTOList)) {
            return;
        }

        SubscribeShopDTOList.stream().forEach(shop -> {
            chainDTO.setShopId(shop.getShopId());
            chainDTO.setShopName(shop.getShopName());
            chainDTO.setSubscribeShopId(shop.getId());
            subscribeShopExecutorService.execute(() ->
                    SubscribeMachineFacadeFactory
                            .getBean(chainDTO.getSubscribeChainEnum())
                            .process(chainDTO));
        });
    }


}

        The following is a simple diagram to describe the cause of the problem. It can be seen that different threads hold the application of the object in the heap, and the store id of the object is constantly being changed by the main thread. If the child thread just started using it, it is equivalent to repeating the change. Calculation, but once the store is used to get the machine information to calculate the result, it will cause problems to combine the store and the result to push.

 

 It is also very simple to modify the problem. After deep copying the object, put the copied object into the child thread.

3. Summary

        The problem is very simple, there are too many places where the requirements are scattered, and this kind of bug is written without paying attention, and even the habit of independent multi-threaded objects is forgotten.

おすすめ

転載: blog.csdn.net/m0_69270256/article/details/125439159