多线程的CountDownLatch的使用

前几天做分页的查询的时候,用多线程做了一下,总的条目数的查找,以及分页调用的程序。

@CrossOrigin(origins = "*",maxAge = 3600)
@PostMapping(value="/GetTByCondition")
public Map<String,Object> getIdModelPageList
        (@RequestBody ModelIdConditionInputDTO modelIdConditionInputDTO)
{
    Map<String,Object> map = new HashMap<>(16);
    //CountDownLatch latch=new CountDownLatch(2);
    try {
        taskExecutor.execute(() -> {
            map.put("Tdto",idModelService.getPage(modelIdConditionInputDTO));
            //latch.countDown();
        });

        taskExecutor.execute(() -> {
            map.put("RowCount",idModelService.getCount(modelIdConditionInputDTO));
            //latch.countDown();
        });
        //latch.await();
        json = this.setJson(200, GET_SUCESS, map);
    }
    catch (Exception e)
    {
        logger.error(e.getMessage());
    }
    return json;
}

返回结果

多线程的CountDownLatch的使用

可以看到查到的是空值,根据bug调用,发现了问题。

首先

多线程的CountDownLatch的使用

我定义的变量每次request的时候会自动为null,这个其实没什么。关键是下边二个

多线程的CountDownLatch的使用

这二个service是要去数据库dao的。当我们request的时候,它直接去i/o,这过程需要时间。主线程也不管他直接返回给我个空值。

然后假如我再重新请求一次的话又会重复原来的结果。

我们试着把

Map<String,Object> map = new HashMap<>(16);

这段代码改一改看是不是复合我的猜想。

多线程的CountDownLatch的使用

有意思的事情出现了,这是第一次request

多线程的CountDownLatch的使用

这是第二次request

多线程的CountDownLatch的使用 

相信大家都已经看出端倪了。第一次request的时候,程序还没来得及取到数据(也就是那两次dao), 程序已经response了。导致返回的是空。第二次为啥有数据?第二次也是没来及插入数据的,那是第一次response以后,dao取出数据放在hashmap里的。也是说你第二次取的是第一次还没来得及返回的数据!!!因为我把hashmap定义为静态变量,所以会保存上次的值!!!我,们用CountDownLatch控制一下顺序。重启一下程序。

@CrossOrigin(origins = "*",maxAge = 3600)
@PostMapping(value="/GetTByCondition")
public Map<String,Object> getIdModelPageList
        (@RequestBody ModelIdConditionInputDTO modelIdConditionInputDTO)
{
     Map<String,Object> map = new HashMap<>(16);
    CountDownLatch latch=new CountDownLatch(2);
    try {
        taskExecutor.execute(() -> {
            map.put("Tdto",idModelService.getPage(modelIdConditionInputDTO));
            latch.countDown();
        });

        taskExecutor.execute(() -> {
            map.put("RowCount",idModelService.getCount(modelIdConditionInputDTO));
            latch.countDown();
        });
        latch.await();
        json = this.setJson(200, GET_SUCESS, map);
    }
    catch (Exception e)
    {
        logger.error(e.getMessage());
    }
    return json;
}

 多线程的CountDownLatch的使用

ok,结果和预期的一样。

其实这个bug挺有迷惑性的。我一开始还以为是赋值的错误,调试了半天。方向都没找对。当然最关键的是我对多线程的理解不够透彻,忽略了dao到数据库的时间差。