同学们,帮我表弟检查下代码?

背景

表弟刚参加工作半年,就遇到批量调用接口返回错误的问题,刚好是周五遇到让周六加班弄完,由于周六本是休息,表弟积极性很低,于是直接选择短平快的方式先应付上去,并且运行了一下,说日志有空指针报错,但核对了一下数据库数据正常,暂时没发现问题。

为了保险起见让我帮忙给review一下

表弟说用大模型分析,老是回答说存在问题,让换一种写法,但大模型的那些问题像是在专业的胡说,不太放心自己临时写的代码。说经常看很多人喜欢review代码,就跑过来让我看一下,我看完后心中已有数。但为了表弟面前表现的更专业,故将其代码去除所有业务信息,做了最简化处理让各位也来点评一下,博采众长。

顺便吆喝一句,技术大厂跳板,前后端/测试,多地捞人机会,待遇还可以~感兴趣的冲冲!

表弟的代码(极简版)

表弟的环境是jdk8的单体服务,此接口调用频率很低,但一旦调用并发量很多。

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.locks.ReentrantLock;

@Slf4j
@RequestMapping("/queue")
@RestController
public class QueueController {

    //服务一旦宕机,队列消息就会全部丢失
    private static final Queue<String> queue = new LinkedBlockingQueue<>(10000);

    private static final ReentrantLock lock = new ReentrantLock();

    /**
     * 通过内存占用换取接口的并发能力,请求进来先进队列里排队,最后一个走的线程检查一下队列是否处理完成
     * @param id 模拟任务对象
     */
    @RequestMapping("/offer")
    public void test(@RequestParam("id")String id){
        if(id != null) {
            //模拟生产任务
            boolean offered = queue.offer(id);
            if(!offered){
                log.error("消息进入队列失败:{}",id);
            }
        }
        boolean isLock = lock.tryLock();
        if(isLock) {
            try {
                while (!queue.isEmpty()) {
                    String poll = queue.poll();
                    try {
                        if (poll != null) {
                            log.info("poll:{}", poll);
                            //模拟消费任务耗时,此处可以异步再优化性能
                            Thread.sleep(1000);
                        }
                    }catch (Exception e){
                        log.error("消费任务出错,poll:{},错误信息{}",poll,e.getMessage(),e);
                    }
                }
            } catch (Exception e) {
                log.error("消费任务出现异常,id:{},错误信息:{}",id,e.getMessage(),e);
            } finally {
                if(lock.isHeldByCurrentThread()){
                    lock.unlock();
                    //进入判断前可以加个10ms的睡眠时间,进一步降低高并发下总是此线程拿到锁的可能,从而不断递归导致栈溢出
                    if(!queue.isEmpty()){
                        log.info("清理队列剩余任务,size:{}",queue.size());
                        test(null);
                    }
                }
            }
        }
        log.info("生产者执行完成,size:{}",queue.size());
    }
}

——转载自:我的咖啡要加糖

#牛客创作赏金赛#
全部评论

相关推荐

点赞 评论 收藏
分享
不愿透露姓名的神秘牛友
07-03 16:22
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务