如何在java中使单例bean线程安全并具有更好的性能?

问题描述 投票:0回答:1

我正在尝试与多个用户测试下面的代码。但由于该类是由 spring 管理的单例,因此只有一个已创建的对象,并且多个线程试图访问同一对象。

由于输出字符串不一致。尝试通过在 appLogger 方法中使用 Synchronized 关键字来解决此问题。它正在按预期工作。但我们需要在性能上做出妥协。

如何在多线程环境中处理单例bean,并通过实例变量(StringBuilder)修改来获得更好的性能?

编辑代码,添加aggregateLogger方法。此方法会将字符串聚合到已在类级别声明的现有 StringBuilder,以便 stringbuilder 将具有来自 appLogger 和aggregateLogger 方法的聚合日志。

    @Aspect
    @Slf4j
    @Component
    public class A{
     private StringBuilder builder = new StringBuilder();
     public StringBuilder getSb(){
     return builder;
     }
     public void appendToSb(String s){
     builder.append(s);
     }

    @Around("@annotation(execTimeLogger)")
    public Object appLogger(ProceedingJointPoint pjp){
     long startTime = xxx;
     Object object = pjp.proceed();
     long endTime = xxx;
     String str = "Hello";
     appendToSb(str);
    return object;
    }

    @Around("@annotation(logger)")
    public Object aggregateLogger(ProceedingJointPoint pjp){
     long startTime = xxx;
     Object object = pjp.proceed();
     long endTime = xxx;
     String str = "World";
     appendToSb(str);
     log.info(getSb().toString()); // o/p will be Aggregated Log 
     getSb().setLength(0);
    return object;
    }
    
}
java spring-boot multithreading singleton spring-aop
1个回答
0
投票

你的设计是错误的,请原谅我这么直率。即使在您想要记录的一项业务事务中,也可能有多个应用程序层在多个线程中执行多项操作。为什么所有这些都必须在一条日志消息中?通常,您使用某种客户和/或事务 ID 或任何正确标识您想要跟踪和记录的逻辑实体的内容来记录所有消息。大多数日志记录框架都使用某种“映射诊断上下文 (MDC)”来实现此目的。无论您登录到控制台还是数据库或日志聚合器(如 Logstash 或 Graylog),您都可以按您感兴趣的实体或事务进行搜索、过滤和聚合,找到所有相应的日志消息。无需将它们全部放入一条日志消息中。 当然,您可以利用方面来进行日志记录,而不是用日志语句污染您的核心代码。分解出像日志记录这样的横切关注点是 AOP 的主要优点之一。但你应该做对。因此,您的单例方面要么使用 MDC,要么在某种映射中进行自己的簿记。我建议使用您的日志框架已经提供的工具,并让方面专注于它最擅长的事情,即拦截正确的连接点。

© www.soinside.com 2019 - 2024. All rights reserved.