阿里巴巴代码规范学习

1.volatile
volatile是一个特征修饰符(type specifier)。volatile的作用是作为指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值。
volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。

如果两个线程想要取同一个值,A已经更新了数据,B还没有更新数据,那么为了让B取得最新的数据,设置变量为volatile

public class MyData {//int number = 0; // 没加volatile关键字volatile int number = 0;int changeNumber() {return this.number = 60;}
}
public class violate {// 验证可见性public static void main(String[] args) {MyData myData = new MyData();new Thread("AAA") {@Overridepublic void run() {try {Thread.sleep(3000);// 睡3秒后调用changeNumber方法将number改为60System.err.println(Thread.currentThread().getName()+  " update number to " + myData.changeNumber());} catch (InterruptedException e) {e.printStackTrace();}};}.start();// 主线程while (myData.number == 0) {}// 如果主线程读取到的一直都是最开始的0,//将造成死循环,这句话将无法输出System.err.println(Thread.currentThread().getName()+ " get number value is " + myData.number);}}

2.深拷贝浅拷贝

public class Age implements Cloneable {//年龄类的成员变量(属性)private int age;//构造方法public Age(int age) {this.age=age;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return this.age+"";}@Overridepublic Object clone() {Object obj=null;try {obj=super.clone();} catch (CloneNotSupportedException e) {e.printStackTrace();}return obj;}
}

在 Student 的 clone() 方法中,需要拿到拷贝自己后产生的新的对象,然后对新的对象的引用类型再调用拷贝操作,实现对引用类型成员变量的深拷贝。

public class Student implements Cloneable{private Age aage;//学生类的成员变量(属性),其中一个属性为类的对象private String name;private int length;//构造方法,其中一个参数为另一个类的对象public Student(String name, Age a, int length) {this.name=name;this.aage=a;this.length=length;}//eclipe中alt+shift+s自动添加所有的set和get方法public String getName() {return name;}public void setName(String name) {this.name = name;}public Age getaAge() {return this.aage;}public void setaAge(Age age) {this.aage=age;}public int getLength() {return this.length;}public void setLength(int length) {this.length=length;}/*设置输出的字符串形式*/@Overridepublic String toString() {return "姓名是: "+this.getName()+", 年龄为: "+this.getaAge().toString()+", 长度是: "+this.getLength();}@Overridepublic Object clone() {Object obj=null;//调用Object类的clone方法——浅拷贝try {obj= super.clone();} catch (CloneNotSupportedException e) {e.printStackTrace();}
//        //调用Age类的clone方法进行深拷贝
//        //先将obj转化为学生类实例Student stu=(Student)obj;//学生类实例的Age对象属性,调用其clone方法进行拷贝stu.aage=(Age)stu.getaAge().clone();return obj;}
}

深拷贝

public static void main(String[] args) {Age a=new Age(20);Student stu1=new Student("摇头耶稣",a,175);//通过调用重写后的clone方法进行浅拷贝Student stu2=(Student)stu1.clone();System.out.println(stu1.toString());System.out.println(stu2.toString());System.out.println();//尝试修改stu1中的各属性,观察stu2的属性有没有变化stu1.setName("name");//改变age这个引用类型的成员变量的值a.setAge(99);//stu1.setaAge(new Age(99));    //使用这种方式修改age属性值的话,stu2是不会跟着改变的。因为创建了一个新的Age类对象而不是改变原对象的实例值stu1.setLength(216);System.out.println(stu1.toString());System.out.println(stu2.toString());}

深拷贝结果,会创建stu2对象,对象的数据不会随着stu1变化

浅拷贝
浅拷贝(Shallow Copy):①对于数据类型是基本数据类型的成员变量,浅拷贝会直接进行值传递,也就是将该属性值复制一份给新的对象。因为是两份不同的数据,所以对其中一个对象的该成员变量值进行修改,不会影响另一个对象拷贝得到的数据。②对于数据类型是引用数据类型的成员变量,比如说成员变量是某个数组、某个类的对象等,那么浅拷贝会进行引用传递,也就是只是将该成员变量的引用值(内存地址)复制一份给新的对象。因为实际上两个对象的该成员变量都指向同一个实例。在这种情况下,在一个对象中修改该成员变量会影响到另一个对象的该成员变量值。

 public class Age implements Cloneable {//年龄类的成员变量(属性)private int age;//构造方法public Age(int age) {this.age=age;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return this.age+"";}@Overridepublic Object clone() {Object obj=null;try {obj=super.clone();} catch (CloneNotSupportedException e) {e.printStackTrace();}return obj;}
}
public class Student implements Cloneable{private Age aage;//学生类的成员变量(属性),其中一个属性为类的对象private String name;private int length;//构造方法,其中一个参数为另一个类的对象public Student(String name, Age a, int length) {this.name=name;this.aage=a;this.length=length;}//eclipe中alt+shift+s自动添加所有的set和get方法public String getName() {return name;}public void setName(String name) {this.name = name;}public Age getaAge() {return this.aage;}public void setaAge(Age age) {this.aage=age;}public int getLength() {return this.length;}public void setLength(int length) {this.length=length;}/*设置输出的字符串形式*/@Overridepublic String toString() {return "姓名是: "+this.getName()+", 年龄为: "+this.getaAge().toString()+", 长度是: "+this.getLength();}@Overridepublic Object clone() {Object obj=null;//调用Object类的clone方法——浅拷贝try {obj= super.clone();} catch (CloneNotSupportedException e) {e.printStackTrace();}
//        //调用Age类的clone方法进行深拷贝
//        //先将obj转化为学生类实例Student stu=(Student)obj;//学生类实例的Age对象属性,调用其clone方法进行拷贝stu.aage=(Age)stu.getaAge().clone();return obj;}
}
 public static void main(String[] args) {Age a=new Age(20);Student stu1=new Student("摇头耶稣",a,175);//通过调用重写后的clone方法进行浅拷贝Student stu2=(Student)stu1.clone();System.out.println(stu1.toString());System.out.println(stu2.toString());System.out.println();//尝试修改stu1中的各属性,观察stu2的属性有没有变化stu1.setName("name");//改变age这个引用类型的成员变量的值a.setAge(99);`在这里插入代码片`//stu1.setaAge(new Age(99));    //使用这种方式修改age属性值的话,stu2是不会跟着改变的。因为创建了一个新的Age类对象而不是改变原对象的实例值stu1.setLength(216);System.out.println(stu1.toString());System.out.println(stu2.toString());}

通过拷贝构造方法进行了浅拷贝,各属性值成功复制。

基本数据类型是值传递,所以修改值后不会影响另一个对象的该属性值;

引用数据类型是地址传递(引用传递),所以修改值后另一个对象的该属性值会同步被修改。

String类型非常特殊,一个字符串类型的成员变量来进行说明。首先,String类型属于引用数据类型,不属于基本数据类型,但是String类型的数据是存放在常量池中的,也就是无法修改的!也就是说,当我将name属性从“摇头耶稣”改为“name"后,并不是修改了这个数据的值,而是把这个数据的引用从指向”摇头耶稣“这个常量改为了指向”name“这个常量。在这种情况下,另一个对象的name属性值仍然指向”摇头耶稣“不会受到影响。


3.【强制】在日志输出时,字符串变量之间的拼接使用占位符的方式。
说明:因为 String 字符串的拼接会使用 StringBuilder 的 append()方式,有一定的性能损耗。使用占位符仅是替换动作,可以有效提升性能。
正例:logger.debug(“Processing trade with id: {} and symbol: {}”, id, symbol);
4.【强制】对于 trace/debug/info 级别的日志输出,必须进行日志级别的开关判断。
说明:虽然在 debug(参数)的方法体内第一行代码 isDisabled(Level.DEBUG_INT)为真时(Slf4j 的常见实现
Log4j 和 Logback),就直接 return,但是参数可能会进行字符串拼接运算。此外,如果 debug(getName())
这种参数内有 getName()方法调用,无谓浪费方法调用的开销。
我在打debug日志的时候,调用了getName()方法,这个时候,即使我们配置只打INFO级别的日志,运行到这段代码的时候,仍然会调用user.getId()方法,造成不必要的开销。
正例:
// 如果判断为真,那么可以输出 trace 和 debug 级别的日志
if (logger.isDebugEnabled()) {
logger.debug(“Current ID is: {} and name is: {}”, id, getName());
}

5.在 varchar 字段上建立索引时,必须指定索引长度,没必要对全字段建立索引,根据实际文本区分度决定索引长度。

索引的长度与区分度是一对矛盾体,一般对字符串类型数据,长度为 20 的索引,区分度会高达 90%
以上,可以使用 count(distinct left(列名, 索引长度))/count()的区分度来确定。
SELECT
COUNT(DISTINCT LEFT(user_name, 4)) / COUNT(
)
FROM
my_user
6.不要使用 count(列名)或 count(常量)来替代 count(),count()是 SQL92 定义的标
准统计行数的语法,跟数据库无关,跟 NULL 和非 NULL 无关。
说明:count(*)会统计值为 NULL 的行,而 count(列名)不会统计此列为 NULL 值的行。
7.count(distinct col) 计算该列除 NULL 之外的不重复行数,注意 count(distinct col1,
col2) 如果其中一列全为 NULL,那么即使另一列有不同的值,也返回为 0。
8.【强制】当某一列的值全是 NULL 时,count(col)的返回结果为 0,但 sum(col)的返回结果为
NULL,因此使用 sum()时需注意 NPE 问题。
正例:可以使用如下方式来避免 sum 的 NPE 问题:SELECT IFNULL(SUM(column), 0) FROM table;
9.代码中写分页查询逻辑时,若 count 为 0 应直接返回,避免执行后面的分页语句。

10.不得使用外键与级联,一切外键概念必须在应用层解决。
说明:(概念解释)学生表中的 student_id 是主键,那么成绩表中的 student_id 则为外键。如果更新学生表中的 student_id,同时触发成绩表中的 student_id 更新,即为级联更新。外键与级联更新适用于单机
低并发,不适合分布式、高并发集群;级联更新是强阻塞,存在数据库更新风暴的风险;外键影响数据库的插入速度。

11.因国际化需要,所有的字符存储与表示,均采用 utf8 字符集,那么字符计数方法需 要注意。
说明:
SELECT LENGTH(“轻松工作”); 返回为 12
SELECT CHARACTER_LENGTH(“轻松工作”); 返回为 4
如果需要存储表情,那么选择 utf8mb4 来进行存储,注意它与 utf8 编码的区别。

redis stream

一、AOP删除添加数据
1.ProceedingJoinPoint args 会得到传输对象所有的参数
2.ProceedingJoinPoint proceed 会对数据进行处理,找到指定的进程,可以对进程的数据进行处理。
问题:
重复AOP会不会删除数据
二、redis Stream线程池
Redis stream 设置自己的线程池,线程池内的线程是需要线程工厂来生成。整个线程工厂产生的线程具有相同的group、namePrefix。当运行未知的Java程序的时候,该程序可能有恶意代码(删除系统文件、重启系统等),为了防止运行恶意代码对系统产生影响,需要对运行的代码的权限进行控制,这时候就要启用Java安全管理器。

static class DefaultThreadFactory implements ThreadFactory {private static final AtomicInteger poolNumber = new AtomicInteger(1);private final ThreadGroup group;private final AtomicInteger threadNumber = new AtomicInteger(1);private final String namePrefix;DefaultThreadFactory() {// 声明安全管理器SecurityManager s = System.getSecurityManager();// 得到线程组group = (s != null) ? s.getThreadGroup() :Thread.currentThread().getThreadGroup();// 线程名前缀,例如 "pool-1-thread-"namePrefix = "pool-" +poolNumber.getAndIncrement() +"-thread-";}/*** 用于创建一个线程*/public Thread newThread(Runnable r) {Thread t = new Thread(group, r,namePrefix + threadNumber.getAndIncrement(),0);// 设置线程t为前台线程if (t.isDaemon())t.setDaemon(false);// 设置线程t的优先级为5if (t.getPriority() != Thread.NORM_PRIORITY)t.setPriority(Thread.NORM_PRIORITY);return t;}
}

@EnableConfigurationProperties使用
如果一个配置类只配置@ConfigurationProperties注解,而没有使用@Component,那么在IOC容器中是获取不到properties 配置文件转化的bean。@EnableConfigurationProperties 是把指定类的属性又注入了一次。

@FunctionalInterface注解的接口中只能有一个抽象方法,可以有多个静态方法或者默认方法, 每一个该类型的lambda表达式都会被匹配到这个抽象方法。

三、redis stream API
1.添加数据
XADD KEY *(自增id) 添加的值
XADD attack * key value
2.截取数据,会在redis里面只保留两条数据
XTRIM KEY MAXLEN 限制最大长度
XTRIM attack MAXLEN 2
3.删除数据
XDEL KEY ID
XDEL attack 1619776307832-0
4.查询几条数据
XRANGE key start end [COUNT count]
xrange KEY - + COUNT 2
5.Redis stream长度
XLEN KEY
6.反向查询数据,查询的是最新添加的数据
XREVRANGE key end start [COUNT count]
XREVRANGE event + - count 1
7.XREAD 阻塞查询
可以查询存入最久的两条数据,attack是stream的名称
XREAD COUNT 2 STREAMS attack 0-0
可以查全部数据,event是stream的名称
XREAD STREAMS event 0-0
BLOCK是阻塞的时间,显示这个ID号1000ms内添加的数据
XREAD BLOCK 1000 STREAMS attack 1620119650161-0
数据反馈的可以是已经添加在这个ID号后面的历史数据,或者是在1000ms内新添加的数据

阻塞5000ms,只能显示在阻塞后添加的数据,不能显示历史数据
XREAD BLOCK 5000 COUNT 10 STREAMS attack $
8.xinfo
查询stream的基本信息
XINFO STREAM attack
查询attack所在的group的名称,consumer的个数
XINFO GROUPS attack
查询group下属的consumer
XINFO CONSUMERS attack attack_group
最后一字段是consumer空闲时间。
9.xpending
先是创建消费者c1消费消息,之后因为消息没有回复ack,会是pending的状态

Ack key group ID
消息ack之后,就没有pending的消息了

用于查看消费但是还没有ack的消息
xpending key group
xpending message read_group(消息已经消费了)

阿里巴巴代码规范学习+redis stream相关推荐

  1. IDEA 阿里巴巴代码规范检查插件使用

    1.问题概要 大家都想写出规范的代码,可规范的标准是什么勒,估计每个人心中的标准都不是完全一致的 在分工合作越来越精细化的时代,我们需要一个最大程度接近公认的规范,这里我们以阿里巴巴的代码规范作为参考 ...

  2. 阿里巴巴编码规范学习及应用

    点击 Mr.绵羊的知识星球 解锁更多优质文章. 目录 一.介绍 二.学习及应用 三.总结 一.介绍 无规矩不成方圆,无规范不能协作.近万名阿里Java技术精英的经验总结,并经历了多次大规模一线实战检验 ...

  3. Idea之阿里巴巴代码规范

    文章目录 Idea之阿里巴巴规范 1. 代码格式化 1.1 google的格式化插件 1.1.1 google-java-format安装 1.1.2 Checkstyle-IDEA安装 1.1.3 ...

  4. C++代码规范 学习笔记

    C++代码规范 参考https://blog.csdn.net/zang141588761/article/details/50608736 一.文件排版方面 1. 包含头文件 • 先系统头文件,后用 ...

  5. 阿里巴巴代码规范扫描

    1.简介 接手前同事的代码一段时间了,看得我真心难受.没有注释,各种奇怪的命名,比如你能看到一个类里面出现getSetCache和getCacheSet两个方法,传参也不同,(我也不知道这个人是不是方 ...

  6. 阿里巴巴代码规范-note

    阿里巴巴在之前的云栖大会上正式发出了 阿里巴巴Java开发手册. 并发布相关的Idea插件. 具体的信息可以到Github主页 p3c查看. 最近将手册重新学习了一遍, 发现在之前的工程项目里面, 有 ...

  7. 2018.3.2版本idea 安装阿里巴巴代码规范

    阿里规范插件GitHub地址:https://github.com/alibaba/p3c IDEA安装该插件步骤: 1.打开IDEA,File-> Setteings->Plugins- ...

  8. 阿里巴巴代码规范【强制】

    一.编程规约 (一)命名风格 代码中的命名均不能以下划线或美元符号开始,也不能以下划线或美元符号结束. 反例:_name / $name / name_ / name$ 严禁使用拼音与英文混合的方式, ...

  9. Eclipse安装阿里巴巴代码规范插件p3c

    第一步:进入Help->Install New Software 第二步:输入 https://p3c.alibaba.com/plugin/eclipse/update  第三步:安装完成后重 ...

最新文章

  1. spring实例教程
  2. python能做软件吗-python能够做软件的自动化测试吗?
  3. Java初级学习(转载http://www.cnblogs.com/biehongli/p/5737612.html)
  4. 信用差价Definition of 'Credit Spread'
  5. np.identity()
  6. C#通用类Helper整理
  7. c#switch语句判断成绩_switch语句成绩等级例子
  8. python 编译器_Python教程:编译器与解释器
  9. Linux管理传世经典:Linux 系统管理技术手册(第二版) 中文高清版下载
  10. 基础的数据处理(1)—出租车数据的基础处理,由gps生成OD(pandas)
  11. 电脑端查看CAD图纸也能非常方便
  12. JNPF.java前后端分离框架,SpringBoot+SpringCloud开发微服务平台
  13. Origin 2019b安装
  14. lidar及tof应用,三维点,线,面求解算法,手眼标定,点云匹配及三角剖分、结构光和TOF深度图
  15. vue实现标题导航,tab选项卡(一看就会)
  16. 计算机更换桌面背景的步骤,怎么更换电脑桌面背景图片
  17. 高考加油别学计算机图片,高考加油励志说说带图片,2020高考加油说说配图
  18. 中国传统的节日(端午节)
  19. 学计算机怎么预防脱发,电脑工作者应如何预防脱发?
  20. SQL Server中事务日志已满的原因以及解决办法

热门文章

  1. 关于软件的空间占用,安装目录
  2. K-Means和轮廓系数
  3. BIOS和UEFI区别,以及Boot Loader【下】
  4. “好吃的”奥利奥 Android 8.0 正式发布:更快、更强大、更安全
  5. 金蝶云星空-不重启IIS开发插件
  6. Linux音频驱动之四:I2S 总线操作接口
  7. 我热爱计算机作文450字,热爱体育的我作文450字
  8. JS函数式编程【译】5.1 范畴论
  9. 达梦数据库使用:图形界面、访问方式、启动及关闭
  10. 十年开发,连登陆接口都写这么烂...