多线程实例

场景如下

有多个品牌,每个品牌下有多个商品,现在要过滤掉其中没有商品的品牌。

除了没有商品的可能,还有用户被屏蔽的可能,因此还有一道过滤逻辑。

比如康师傅品牌下有康师傅红茶、康师傅方便面等等,盼盼品牌下啥也没有,就要把盼盼过滤掉,康师傅留下。

过滤的线程如下

//得到品牌下商品的个数
class CountGoods implements Callable<Integer>{
    //分页参数
    PageRequest request;
    //品牌id
    Long brandId;
    //所有品牌列表,如果传入的品牌无效,就将此列表的该品牌去掉
    CopyOnWriteArrayList<Long> brandList;

    public CountGoods(PageRequest request, Long brandId, CopyOnWriteArrayList<Long> brandList){
        this.request = request;
        this.brandId = brandId;
        this.brandList = brandList;
    }

    @Override
    public Integer call() throws Exception{
        //获取所有品牌下商品
        Map<Long,List<Long>> brandSkuMap = getBrand(request.getBpin());
        //获取该品牌下的商品
        List<Long> subSkuList = brandSkuMap.get(fBrandId);
        //防止空数据
        if(subSkuList == null){
            return 0;
        }
        //对该品牌下的商品进行过滤
        List<GoodsInfo> goodsInfo= goodsRpc.synFilterSku(request.getBpin(), subSkuList);
        if(goodsInfo== null){
            return 0;
        }else{
            if(goodsInfo.size() == 0){
                brandList.remove(brandId);
            }
            return goodsInfo.size();
        }
    }
}

多线程进行过滤

public List<Long> filterBrandList(PageRequest request, List<Long> IdList){
    List<Callable<Integer>> calls = new ArrayList();
    //过滤逻辑
    Iterator<Long> iterator = IdList.iterator();
    while(iterator.hasNext()){
        Long brandId =iterator.next();
        Callable call = new countId(request, brandId , (CopyOnWriteArrayList<Long>) IdList);
        calls.add(call);
    }

    ExecutorService cacheThreadPool = new ThreadPoolExecutor(5, 10, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>());
    List<Future<Integer>> callableResult = null;
    try{
        if(calls != null && calls.size() > 0){
            callableResult = cacheThreadPool.invokeAll(calls);
        }
    }catch (Exception e){
        e.printStackTrace();
        LogUtil.printErrorLog(log, "多线程过滤品牌出现异常");
    }finally {
        cacheThreadPool.shutdown();
    }
    return fontBrandIdList;
}

缺陷

毫无疑问,这段代码一上到线上运行,就出了bug。

报错很奇怪,说是执行线程时,执行线程里的过滤操作出错了,但是有部分是执行成功。

百思不得其姐,终于周末想到一个问题,我似乎没给它阻塞队列……

注意了,这个线程池的阻塞队列有问题,需要修改,这样只能有10个任务过来,更多的会被拒绝。修改线程池的阻塞队列类型即可。

new SynchronousQueue<Runnable>()

这个是没有阻塞队列的意思。

修改如下:

ExecutorService cacheThreadPool = new ThreadPoolExecutor(5, 10, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(100))

但是还有一个问题:

注意了,这样将线程池直接在service方法中new出来是不对的,因为这样没法复用线程。比如,两个人同时访问这个方法,就分别new了一个线程池,没有用同一个线程池,而且,如果并发很高,线程数量激增,很可能会挂掉。应该给个static的线程池,或者单独写一个线程池的bean,在所有地方复用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
DataSnap是一个用于构建多层架构的工具包,可以帮助开发者构建跨平台的客户端-服务器应用程序。在DataSnap中,多线程例子通常用于处理并发请求和提高服务器端的性能。 一个常见的DataSnap多线程例子是创建一个服务器应用程序,该应用程序可以同时处理多个客户端请求。通过使用多线程,可以让服务器同时处理多个客户端的请求,提高了服务器的处理性能和并发能力。 对于一个简单的DataSnap多线程例子,可以通过以下步骤实现: 1. 创建一个DataSnap服务器应用程序,并添加一个多线程处理模块; 2. 在处理模块中编写多线程代码,以便服务器可以同时处理多个客户端请求; 3. 在客户端应用程序中,编写发送并发请求的代码,并测试服务器的处理能力; 4. 通过监控服务器端的性能数据,如处理请求数、响应时间等指标,来验证多线程处理能力的提高。 另外,DataSnap还提供了一些内置的多线程支持,比如TThreadPool和TTask,开发者可以直接使用这些组件来简化多线程编程,提高开发效率。 总之,DataSnap多线程例子可以帮助开发者学习如何利用多线程来提高服务器端的并发处理能力,从而改善客户端-服务器应用程序的性能和稳定性。同时,通过使用DataSnap内置的多线程支持,开发者可以更加方便地实现多线程编程,提高开发效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

weixin_43751710

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值