1.使用threadlocal缓存信息,使用之后没有remove,引起数据错乱。因为threadlocal缓存的数据是线程专属的,如果线程通过线程池复用会导致后面的请求看到之前请求的数据。
2.线程安全的集合框架比如(concurrentHashmap)只针对某一些单个操作是线程安全的,比如add,put,有一些方法不是线程安全的,size,isempty,这样的方法不能用作流程判断,不是一个精确值。
4.copyOnWirteArrayList用在写多读少场景
5.java加锁,锁范围,锁粒度两个方面考虑,锁范围考虑的是锁住哪些内容,锁粒度考虑加什么锁尽可能减少竞争(乐观锁or悲观锁,读写锁,公平非公平锁)
- newFixedThreadPool队列是integer最大值的阻塞队列, newCachedThreadPool最大线程数是integer的最大值。都存在风险。线程池复用需要考虑相同属性或者功能复用,IO和CPU的任务不应该复用一个线程池。java8的parallel stream可以并行处理元素,背后是forkjoinPoll,线程个数是cpu-1,如果是io操作密集型不可用使用。
7.连接池正确姿势:确保连接池复用,程序退出的时候显示关闭释放资源,初始化一些连接,配置合理的最大连接数,设置好监控。
8.http调用设置合理的超时时间,如果使用公共jar包需要考虑jar包是否会自动重试,是否会限制客户端最大并发数。 - spring注解事务需要注意几点:1.注解在public方法上,2.public方法是通过spring注入的bean进行调用的。3.事务回滚只针对runtimeException和error。4.事务传播方式配置
10.比较值的内容,除了基本类型只能使用==外,其他类型都需要使用equals
11.使用new声明的字符串调用intern方法,也可以让字符串进行驻留,但在业务代码中滥用intern,可能会产生性能问题
12.自定义类型,如果要实现comparable,确保equals,hashCode,compareTo三者逻辑一致
13.lombok生成的类,需要注意自动生成的equals,hashCode的逻辑。
14.浮点数计算使用BigDecimal,且使用字符串的构造方法来初始化。浮点数字符串化也要使用BigDecimal。bigDecimal比较使用compareTo方法,equals会比较精度。
15.数值计算需要小心数据溢出,比如long i=int*int,两个int相乘已依然用int存储,之后才会赋给i,用int存可能溢出。
16.Arrays.asList和List.subList得到的List不是独立的。map和list比,通过key查找value很快,但是占用内存更多,需要平衡时间和空间。linkedList只有在头和尾插入速度会很快,随机插入性能还不如arrayList,优先用arrayList,连linkedList作者自己都不用。
17.java空指针问题
场景:自动拆箱,容器内容不支持空或者容器为空,如果一行可能多个空指针引起,定位不到原因可以参考:Java故障诊断神器Arthas
自动拆箱空指针解决思路:Optional.ofNullable(i).orElse(0)
字符串比较空指针解决思路:”OK“.equals(s), Objects.equal(s,t)
方法返回值为list无法判断是否为空解决思路:Optional.ofNullable(list).orElse(Collections.emptyList());
迭代获取熟悉需要多次判空解决思路:Optional.ofNullable(fooService)
.map(FooService::getBarService)
.filter(barService -> "OK".equals(barService.bar()))
.ifPresent(result -> log.info("OK"));
18.mysql null问题
mysql sum没有统计到任何记录会返回null而不是0.
mysql count字段不会统计空值
mysql 判断是否为空的时候不能== 要用is null
18.异常处理
a.框架层面统一异常处理只能做兜底,不能作为异常处理方案
b.每一层的异常应该各自处理,自己处理不了才返回给上一层
c.捕获异常直接生吞,异常没有打印堆栈
d.finally里面不要抛出任何异常,会吞掉
e.异常不要定义成静态变量,会导致异常堆栈与真实报错的地方不符
f.线程池如果execute提交,任务需要处理异常,否则会导致线程退出重新创建线程,达不到线程复用的效果。如果是submit提交通过future.get来捕获异常
19.序列化
a.使用jackson反序列化字符串成对象的时候,只会使用默认的构造函数
b.枚举类不要作为接口的入参或者出参属性,序列号和反序列化有问题
20.时间日期处理
SimpleDateFormat格式化时间的时候年是小写的y,并且这个类非线程安全,数据与格式不匹配的时候也不报错,建议使用java8的DateTimeFormatter
Period.between计算两个日期的间隔如果是XX年XX月XX天,那只返回XX天。需要使用ChronoUnit.DAYS.between
21.代码写完了,生产就绪工作
健康检测接口
暴露内部应用信息
建立应用监控指标
以Spring Boot有一个Actuator模块为例
22.异步处理注意点
MQ异步处理要注意消息丢失,进行异步补偿。 消费MQ要幂等,消费消息失败不要轻易丢弃,也不要一直消费
网友评论