业务递归记录博客

本文介绍了一种从数据库中获取商品分类信息,并构建成树形结构的方法。通过获取所有商品分类,将其转换为CategoryPOJO对象,然后筛选出顶级分类,递归地为每个顶级分类添加子分类,最终形成完整的商品分类树。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考:https://blog.youkuaiyun.com/frankcheng5143/article/details/52958486

/**
     * 获取所有分类
     * @return
     */
    public final String allCategories() {
        // 获取到原始数据
        List<CategoryPOJO> list = new ArrayList<>();
        //获取到所有的数据
        List<BPEProductCategory> thePrimaryCategories = categoryDAO.allCategories();
        for (BPEProductCategory c : thePrimaryCategories) {
            CategoryPOJO pojo = new CategoryPOJO();
            pojo.setId(c.id);
            pojo.setSortOrder(c.sortOrder);
            pojo.setAmount(productListDAO.numberOfItemsByCategory(c.id));
            pojo.setProductCategoryName(c.productCategoryName);
            pojo.setProductCategoryParentsId(c.productCategoryParentsId);
            list.add(pojo);
        }
        // 最后的结果
        List<CategoryPOJO> categoryList = new ArrayList<>();
        // 找到所有的一级菜单
        for (CategoryPOJO categoryPOJO : list) {
            if(categoryPOJO.getProductCategoryParentsId()!=null) {
                if (categoryPOJO.getProductCategoryParentsId().equals("0")) {
                    // 找到所有的一级菜单
                    categoryList.add(categoryPOJO);
                }
            }
        }

        // 为一级菜单设置子菜单
        for (CategoryPOJO categoryPOJO : categoryList) {
            categoryPOJO.setChildren(this.getChild(categoryPOJO.getId(), list));
        }

        Msg msg = new Msg();
        msg.setData(categoryList);
        return toJSON(msg);
    }

    /**
     * 获取子菜单
     * 
     * @param id
     * @param getdata
     * @return
     */
    public  List<CategoryPOJO> getChild(String id, List<CategoryPOJO> getdata) {
        // 子菜单
        List<CategoryPOJO> childList = new ArrayList<>();
        // 将传过来的id与这里的父id比较
        for (CategoryPOJO categoryPOJO : getdata) {
            if (id.equals(categoryPOJO.getProductCategoryParentsId())) {
                childList.add(categoryPOJO);
            }
        }
        // 把子菜单的子菜单再循环一遍 (递归)
        for (CategoryPOJO categoryPOJO : childList) {
            categoryPOJO.setChildren(getChild(categoryPOJO.getId(), getdata));
        }
        // 递归退出条件
        if (childList.size() == 0) {
            return null;
        }
        return childList;
    }
    

<think>我们正在讨论Java线程池的进阶使用方法及其应用场景,并希望整理成博客形式。以下是一个结构清晰的回答,包含知识点扩展和补充。###Java线程池进阶指南####1.线程池的核心参数Java线程池通过`ThreadPoolExecutor`类实现,其构造函数包含7个核心参数:```javapublicThreadPoolExecutor(intcorePoolSize,//核心线程数intmaximumPoolSize,//最大线程数longkeepAliveTime,//非核心线程空闲存活时间TimeUnitunit,//时间单位BlockingQueue<Runnable>workQueue,//工作队列ThreadFactorythreadFactory,//线程工厂RejectedExecutionHandlerhandler//拒绝策略)```####2.工作队列类型-**`ArrayBlockingQueue`**:有界队列,需指定容量-**`LinkedBlockingQueue`**:无界队列(默认`Integer.MAX_VALUE`)-**`SynchronousQueue`**:不存储元素的队列,每次插入需等待移除-**`PriorityBlockingQueue`**:带优先级的无界队列####3.拒绝策略当任务数超过`maximumPoolSize+workQueue`容量时触发:-**`AbortPolicy`**(默认):抛出`RejectedExecutionException`-**`CallerRunsPolicy`**:由提交任务的线程直接执行-**`DiscardPolicy`**:静默丢弃新任务-**`DiscardOldestPolicy`**:丢弃队列头部的任务并重试####4.线程工厂定制可自定义线程名称、优先级等:```javaThreadFactorycustomFactory=newThreadFactory(){privateAtomicIntegercount=newAtomicInteger(0);publicThreadnewThread(Runnabler){Threadt=newThread(r,"CustomThread-"+count.incrementAndGet());t.setPriority(Thread.NORM_PRIORITY);returnt;}};```####5.监控与调优-**监控方法**:```javaexecutor.getPoolSize();//当前线程数executor.getActiveCount();//活动线程数executor.getCompletedTaskCount();//已完成任务数```-**调优建议**:-CPU密集型任务:核心线程数≈CPU核数-I/O密集型任务:核心线程数≈CPU核数*(1+平均等待时间/平均计算时间)####6.应用场景-**Web服务器请求处理**:使用`Executors.newFixedThreadPool()`-**异步日志写入**:使用`Executors.newSingleThreadExecutor()`-**定时任务调度**:配合`ScheduledThreadPoolExecutor`-**批处理系统**:使用`ThreadPoolExecutor`自定义参数####7.进阶技巧-**任务链处理**:通过`CompletableFuture`实现异步编排```javaCompletableFuture.supplyAsync(()->fetchData(),executor).thenApplyAsync(data->process(data),executor).thenAccept(result->save(result));```-**资源隔离**:为不同业务创建独立线程池,避免相互影响-**优雅关闭**:```javaexecutor.shutdown();//停止接收新任务if(!executor.awaitTermination(60,TimeUnit.SECONDS)){executor.shutdownNow();//强制终止}```####8.注意事项-避免使用`Executors.newCachedThreadPool()`,可能引发OOM-警惕线程池中的线程泄露(如任务无限等待)-跨线程传递上下文需使用`InheritableThreadLocal`或装饰器模式>**扩展阅读**:Fork/Join框架适用于递归任务分解(如归并排序),其工作窃取算法能提升CPU利用率[^1]。§§相关问题§§1.如何诊断线程池的性能瓶颈?2.线程池配置不当会导致哪些典型问题?3.除了Java原生线程池,还有哪些高性能线程池实现?4.如何实现线程池任务的优先级调度?</think>### Java线程池进阶指南 #### 一、核心进阶用法 1. **自定义线程工厂** 通过`ThreadFactory`定制线程属性(名称/优先级/守护状态): ```java ThreadFactory factory = r -> { Thread t = new Thread(r, "CustomThread-" + System.nanoTime()); t.setPriority(Thread.NORM_PRIORITY); t.setDaemon(false); return t; }; ExecutorService executor = new ThreadPoolExecutor(..., factory); ``` 2. **增强拒绝策略** 实现`RejectedExecutionHandler`接口处理任务溢出: ```java RejectedExecutionHandler policy = (r, executor) -> { // 1. 记录日志 // 2. 暂存到Redis重试队列 // 3. 触发告警 }; ``` 3. **优先级线程池** 使用`PriorityBlockingQueue`实现任务优先级: ```java new ThreadPoolExecutor( coreSize, maxSize, 60L, TimeUnit.SECONDS, new PriorityBlockingQueue<>(100, Comparator.comparing(Task::getPriority)) ); ``` 4. **定时/周期任务强化** `ScheduledThreadPoolExecutor`进阶用法: ```java ScheduledExecutorService scheduler = new ScheduledThreadPoolExecutor(2); // 固定延迟执行(考虑任务执行时间) scheduler.scheduleWithFixedDelay(task, 0, 5, TimeUnit.SECONDS); ``` #### 二、应用场景深度解析 1. **高并发Web服务** - 场景:HTTP请求处理 - 配置: ```java new ThreadPoolExecutor( Runtime.getRuntime().availableProcessors() * 2, // core 100, // max new SynchronousQueue<>(), // 直接传递任务 new ThreadPoolExecutor.CallerRunsPolicy() // 降级策略 ); ``` - 优势:避免线程创建瓶颈,快速响应突发流量[^1] 2. **批量数据处理** - 场景:Excel导入/日志分析 - 关键代码: ```java CompletionService<Result> cs = new ExecutorCompletionService<>(pool); for (DataBatch batch : batches) { cs.submit(() -> processBatch(batch)); } // 按完成顺序获取结果 for (int i=0; i<batches.size(); i++) { Future<Result> f = cs.take(); saveResult(f.get()); } ``` 3. **资源隔离场景** - 金融交易系统:分离支付/查询线程池 - 配置原则: ```mermaid graph LR A[支付线程池] -->|独立资源| B[核心交易] C[查询线程池] -->|独立资源| D[数据检索] E[管理线程池] -->|低优先级| F[日志清理] ``` #### 三、性能优化技巧 1. **动态调参** 运行时调整线程池参数: ```java ThreadPoolExecutor executor = ...; executor.setCorePoolSize(20); // 动态扩容 executor.setMaximumPoolSize(50); ``` 2. **监控指标** 关键监控维度: - 活动线程数:`executor.getActiveCount()` - 队列积压:`executor.getQueue().size()` - 拒绝次数:自定义`RejectedExecutionHandler`统计 3. **上下文传递** 跨线程传递上下文方案: ```java // 使用TransmittableThreadLocal(阿里开源) TransmittableThreadLocal<String> context = new TransmittableThreadLocal<>(); executor.submit(TtlRunnable.get(() -> { System.out.println(context.get()); // 获取父线程上下文 })); ``` #### 四、生产实践要点 1. **规避陷阱** - 避免使用`Executors.newFixedThreadPool()`(可能导致OOM) - 禁止在任务中捕获`Throwable`(应使用UncaughtExceptionHandler) - 线程池销毁必须调用`shutdownNow()` + `awaitTermination()` 2. **扩展方案** - **ForkJoinPool**:递归任务分解(适合计算密集型) - **Spring异步注解**:`@Async("customExecutor")` - **响应式编程**:Project Reactor(非阻塞方案) > **知识扩展**:线程池最佳线程数计算公式: > $$ > N_{threads} = N_{cpu} \times U_{cpu} \times (1 + \frac{W}{C}) > $$ > - $N_{cpu}$:CPU核心数 > - $U_{cpu}$:目标CPU利用率(0.8~0.9) > - $W/C$:等待时间与计算时间比
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值