Java实战-基于JDK的LRU算法实现、优雅的实现代码耗时统计(Spring AOP、AutoCloseable方式)

news2024/12/26 14:19:27

场景

Java中基于JDK的LRU算法实现

LRU算法-缓存淘汰算法-Least recently used,最近最少使用算法

根据数据的历史访问记录来进行淘汰数据,其核心思想是:如果有数据最近被访问过,那么将来被访问的几率也更高

在Java中可以利用LinkedHashMap容器简单实现LRU算法

LinkedHashMap底层就是用的HashMap加双链表实现的,而且本身已经实现了按照访问顺序的存储。

此外,LinkedHashMap中本身就实现了一个方法removeEldestEntry用于判断是否需要移除最不常读取的数,

方法默认直接返回false,不会移除元素,因此只需要重写这个方法,可以实现当缓存满之后,就移除不常用的数据。

新建LruCache类,使其继承LinkedHashMap并重写removeEldestEntry方法

import java.util.LinkedHashMap;
import java.util.Map;

public class LruCache<K,V> extends LinkedHashMap<K,V> {

    private int size;

    public LruCache(int size){
        //accessOrder:默认为false(即默认按照插入顺序迭代)为true时(按照访问顺序迭代,支持实现LRU算法时)
        //作为一般规则,默认负载因子(0.75)提供了一个很好的在时间和空间成本之间进行权衡。数值越高,空间开销,但增加查找成本.
        super(size,0.75f,true);
        this.size = size;
    }

    @Override
    protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
        return size()>size;
    }
}

调用示例

        LruCache<String,Integer> cache = new LruCache<>(4);
        for (int i = 0; i < 10; i++) {
            if(i == 5){
                cache.get("2");
            }
            cache.put(i+"",i);
            System.out.println(i+":"+cache);
            System.out.println("size:"+cache.size());
        }

注意上面的访问,当i == 5时,主动访问了一下2,主要是不希望淘汰掉它

运行结果

        //0:{0=0}
        //size:1
        //1:{0=0, 1=1}
        //size:2
        //2:{0=0, 1=1, 2=2}
        //size:3
        //3:{0=0, 1=1, 2=2, 3=3}
        //size:4
        //4:{1=1, 2=2, 3=3, 4=4}
        //size:4
        //5:{3=3, 4=4, 2=2, 5=5}
        //size:4
        //6:{4=4, 2=2, 5=5, 6=6}
        //size:4
        //7:{2=2, 5=5, 6=6, 7=7}
        //size:4
        //8:{5=5, 6=6, 7=7, 8=8}
        //size:4
        //9:{6=6, 7=7, 8=8, 9=9}
        //size:4

注:

博客:
霸道流氓气质的博客_CSDN博客-C#,架构之路,SpringBoot领域博主

Java中优雅的实现代码耗时统计的方式

1、一般的写法

        long start = System.currentTimeMillis();
        try{
            costTimeHandler();
        } finally {
            System.out.println("cost:"+(System.currentTimeMillis() - start));
        }

优点是简单,适用范围广;缺点是侵入性强,大量的重复代码

2、使用Spring AOP实现代码耗时统计

使用Spring AOP,想要统计某个方法耗时,使用切面可以无侵入的实现。

首先定义自定义注解CountTime,声明周期是运行时,作用域是在方法上

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 自定义注解,统计方法执行消耗时间
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CountTime {
}

然后定义切面类CountTimeAspect,用于处理请求时的内容。

定义一个切面,然后进行环绕通知,进行方法的统计时间,进行日志的输出打印。

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Component
@Aspect
@Slf4j
public class CountTimeAspect {

    //首先定义一个切点
    @org.aspectj.lang.annotation.Pointcut("@annotation(com.ruoyi.demo.actiondemo.CountTime)")
    public void countTime(){

    }

    @Around("countTime()")
    public Object doAround(ProceedingJoinPoint joinPoint){
        Object obj = null;
        try{
            long beginTime = System.currentTimeMillis();
            obj = joinPoint.proceed();
            String methodName = joinPoint.getSignature().getName();
            String className = joinPoint.getSignature().getDeclaringTypeName();
            log.info("类:{},方法:{}耗时为:{}",className,methodName,System.currentTimeMillis()-beginTime);
        }catch (Throwable throwable){
            throwable.printStackTrace();
        }
        return obj;
    }
}

注意这里的包路径与上面的注解的路径一致

然后在需要统计的方法上添加注解CountTime,这里统计定时任务CountTimeTask中testCountTime执行的耗时

import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

@Component
@EnableScheduling
public class CountTimeTask {

    @Scheduled(fixedRateString = "10000")
    @CountTime
    public void testCountTime(){
        try {
            TimeUnit.MILLISECONDS.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

测试以上结果

 

3、java中使用实现AutoCloseable接口实现方法耗时统计

在JDK1.7引入了一个新的接口AutoCloseable,通常它的实现类配合try{}使用,

try(){}执行完毕之后,会调用方法AutoCloseable#close方法。

所以写一个Cost类实现AutoCloseable接口,创建时记录一个时间,

close方法中记录一个时间,并输出时间差值,将需要统计耗时的逻辑放在try(){}代码块中。

public class Cost implements AutoCloseable{

    private long start;

    public Cost(){
        this.start = System.currentTimeMillis();
    }
    @Override
    public void close() throws Exception {
        System.out.println("cost:"+(System.currentTimeMillis() - start));
    }
}

调用示例

        try(Cost cost = new Cost()){
            costTimeHandler();
        }

其中方法costTimeHandler()执行一个耗时操作

    public static void costTimeHandler(){
        try {
            TimeUnit.MILLISECONDS.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

优点是简单,使用范围广泛,且适合统一管理;缺点是依然有代码侵入。

4、也可以使用Java Agent 探针(代理)的技术来实现

在JDK1.5时,引入了java.lang.Instrument包,该包提供了一些工具帮助开发人员在java程序运行时,

动态修改系统中的Class类型。其中,使用该软件包的一个关键组件为Java Agent,它的功能更像是Class类型的转换器,

可以在运行时接收程序外部请求,对Class类型进行修改。

实现方式自行学习。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/593231.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

34. Linux系统下打包qt应用程序

1. 说明 对程序进行打包前需要在Release模式对程序代码进行编译,然后得到编译后的可执行文件,正常情况下这个可执行文件是可以双击打开运行的,如果无法双击运行,可在**.pro**文件内加入下面的代码: QMAKE_LFLAGS += -no-pie TEMPLATE = app同时将main.qml文件中的Window…

【总结】对接达梦数据库DM8详细教程

目录 1.达梦数据库-技术文档2.软件安装包下载2.1 iso 安装版2.2 docker 安装版 3.DM8单机安装部署规范4.安装操作步骤4.1 安装docker4.2 docker安装dameng&#xff08;推荐&#xff09; 5. 启动/停止数据库6.客户端连接使用7.DDL SQL实践7.1 创建表空间7.2 建表语句 8.DML SQL实…

「2023大学生就业报告 」出炉,应届生都去了哪些行业?

2023年的应届毕业生人数再创新高&#xff0c;达到1158万人&#xff0c;是不是开始担忧他们的就业了&#xff1f;别急&#xff0c;最近Boss直聘发布的一组数据&#xff0c;会让这样的担忧有所缓解。 期望薪资有所下降 和增长明显的毕业人数相反的是&#xff0c;这一届大专、本…

网络流量监控及流量异常检测

当今的企业面临着许多挑战&#xff0c;尤其是在监控其网络基础设施方面&#xff0c;需要确保随着网络规模和复杂性的增长&#xff0c;能够全面了解网络的运行状况和安全性。为了消除对网络性能的任何压力&#xff0c;组织应该采取的一项重要行动是使用随组织一起扩展的工具监控…

探究工业设备状态监测的典型对象和常用方法

工业设备状态监测的目的是实时掌握设备的健康状况&#xff0c;及时发现潜在故障迹象&#xff0c;并采取相应的维修和维护措施。通过有效的状态监测&#xff0c;企业可以降低设备故障风险&#xff0c;减少计划外停机时间&#xff0c;提高生产效率&#xff0c;节约维护成本&#…

深兰科技亮相2023数博会:硅基知识大模型推动个人数字化产业

近日&#xff0c;2023中国国际大数据产业博览会 “数字经济与实体经济深度融合”论坛在贵阳举行。腾讯云、京东集团、网易、深兰科技等8家企业负责人进行了行业演讲。 作为2023数博会的专业论坛之一&#xff0c;本次论坛以“数融百业 创变赋新”为主题&#xff0c;从数实融合视…

项目冲突管理机制的4大关键环节

1、冲突预防功能 预先采取一些措施防止冲突的产生&#xff0c;如建立有效的沟通机制。在项目开始前&#xff0c;制定沟通计划、沟通频率和方式&#xff0c;以确保项目成员充分了解自我职责和任务&#xff0c;并自愿分享和讨论。通过有效的沟通机制&#xff0c;最大限度避免不必…

QoS实现之限速

基于流分类&#xff08;MQC&#xff09;的流量监管 前面我们已经介绍过&#xff0c;流量监管一般用于入方向。下面举个例子&#xff0c;详细介绍如何在入方向配置基于MQC的流量监管。如图2所示&#xff0c;企业的语音业务对应的VLAN ID为120&#xff0c;视频业务对应的VLAN ID…

自学网安该怎么做以及怎么找工作?

趁着今天下班&#xff0c;我花了几个小时整理了下&#xff0c;非常不易&#xff0c;希望大家可以点赞收藏支持一波&#xff0c;谢谢。 我的经历&#xff1a; 我 19 年毕业&#xff0c;大学专业是物联网工程&#xff0c;我相信很多人在象牙塔里都很迷茫&#xff0c;到了大三大…

图解LeetCode——146. LRU 缓存

一、题目 请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。 实现 LRUCache 类&#xff1a; LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存int get(int key) 如果关键字 key 存在于缓存中&#xff0c;则返回关键字的值&#xff0c;…

什么才是自动化测试框架?最流行的自动化测试框架整理,你的进阶之路...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 Python自动化测试&…

Smartbi助力航天百亿级遥测数据实现秒级查询

“Smartbi全程参与了火星探测任务、中国载人空间站建设任务&#xff0c;为航天任务参战单位提供专业、易用、高性能的实时数据查询分析监控平台&#xff0c;实现航天器飞行状态监测和预警&#xff0c;让咱们的科研人员专注聚焦科研工作&#xff0c;保障航天任务顺利进行。Smart…

Benewake(北醒) 快速实现 TF02-i-RS485 与电脑通信操作说明

目录 一、前言二、工具准备1. USB-RS485 转接器2. TF02-i-RS4853. 兆信直流电源4.连接线、绝缘胶带、螺丝刀5. PC&#xff1a;Windows 系统6. 串口助手软件 三、连接方式1. USB-RS485 转接板接口说明2. TF02-i-RS485 引脚定义3. 连接图 四、TF02-i-RS485 与电脑通信操作说明1. …

js中+new Date()

在学习js过程中遇到了这样的写法&#xff1a; var nownew Date(); 在这段代码中有一个号&#xff0c;上网查阅得知在前面加一个号是涉及到了隐式转换&#xff0c;也就是触发对象执行valueof进行求值。 valueof可以用来得到现在时间距离1970.1.1总的毫秒数&#xff1a; var …

Android12之源码手动生成aidl对应java/cpp/ndk/rust服务(一百五十三)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

【自动化项目实战】博客系统

目录 1.博客自动化测试用例 2.准备工作 3.将手工测试用例转化为自动化测试用例 3.1 初始化动作 3.2 登录 3.3 博客列表博客数量 3.4 查看全文 3.5 写博客&发表博客 3.6 删除 3.7 注销 4.总代码 &#x1f308;这节文章我们讲解一个实战项目——博客系统。首先我…

在前公司年薪38W,经人内推腾讯居然被拒了···

末流院校&#xff0c;带17人研发团队&#xff0c;到手38w股票20w&#xff0c;过硬的技术让我觉得可以出去“闯闯”;内推到某大厂&#xff0c;电话里聊得挺好&#xff0c;结果第二天说不给安排面试了…… 被拒绝很正常&#xff0c;想必应该是能力不足&#xff0c;不能满足公司的…

太难了,00后求求你们别这么卷了....

在程序员职场上&#xff0c;什么样的人最让人反感呢? 是技术不好的人吗?并不是。技术不好的同事&#xff0c;我们可以帮他。 是技术太强的人吗?也不是。技术很强的同事&#xff0c;可遇不可求&#xff0c;向他学习还来不及呢。 真正让人反感的&#xff0c;是技术平平&#x…

网络传输(传输介质、通信方式、交换方式)

目录 一、传输介质1.双绞线2.网线安装3.光纤4.无线信道 二、通信方式、交换方式1.通信方式2.同步方式3.交换方式 一、传输介质 1.双绞线 双绞线&#xff1a;将多根铜线按规则缠绕在一起&#xff0c;能够减少干扰&#xff1b;分为无屏蔽双绞线UTP和屏蔽双绞线STP&#xff0c;都…

PCIE学习

目录 一、PCIE结构1、层次结构2、数据包TLPDLLP PCIE寄存器配置1、基址寄存器的作用2、基址寄存器的位置 三、PCIE读取数据 一、PCIE结构 1、层次结构 绝大多数的总线或者接口&#xff0c;都是采用分层实现的。PCIe也不例外&#xff0c;它的层次结构如下&#xff1a; PCIe定…