【JAVA】随笔

1.ThreadLocal使用

同一个线程内通过ThreadLocal进行参数传递

ContractDeliverySynService.saveLogInfoMap.set(map);
mapBefore = ContractDeliverySynService.saveLogInfoMap.get();

2.CountDownLatch 判断线程是否执行结束

//1.定义CountDownLatch
CountDownLatch countDownLatch = new CountDownLatch(sqlParam.size());

//2.线程内部对countDownLatch减
OrderSyncCrmTask orderSyncCrmTask = new OrderSyncCrmTask(countDownLatch, resultMap, threadParam, traceId);
pool.submit(orderSyncCrmTask);
//OrderSyncCrmTask内部latch.countDown();

//3.
CountDownLatch.await() 方法在倒计数为0之前会阻塞当前线程,并可设置超时时间
boolean await = countDownLatch.await(OrderSyncCrmTask.staticPushOrderTimeOut, TimeUnit.SECONDS);
if (await) {
log.info("未超时", await);
} else {
log.info("已超时", await);
}

3.javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)报错

原因:JDK版本导致的认证问题
解决:在路径/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.292.b10-1.el7_9.x86_64/jre/lib/security/java.security中找到并修改如下(此前删除TLSv1, TLSv1.1两个认证)
jdk.tls.disabledAlgorithms=SSLv3, RC4, DES, MD5withRSA, DH keySize < 1024,
EC keySize < 224, 3DES_EDE_CBC, anon, NULL

附:
  SSL协议的工作流程:
  服务器认证阶段:
  1)客户端向服务器发送一个开始信息“Hello”以便开始一个新的会话连接;
  2)服务器根据客户的信息确定是否需要生成新的主密钥,如需要则服务器在响应客户的“Hello”信息时将包含生成主密钥所需的信息;
  3)客户根据收到的服务器响应信息,产生一个主密钥,并用服务器的公开密钥加密后传给服务器;
  4)服务器恢复该主密钥,并返回给客户一个用主密钥认证的信息,以此让客户认证服务器。
该认证方式以主服务器为主导

4.通过List.subList实现分页、截取

newList = productBeanList.subList(0, index);

5.手动事务管理

@Autowired
private SqlSessionFactory sqlSessionFactory;

SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH, false);
SyncCrmOrderDetailMapper orderMapper = sqlSession.getMapper(SyncCrmOrderDetailMapper.class);

6.遍历map

jdk8及以后:
Map.forEach方法

7.JDK8时间相关函数

如果是JDK8的应用,可以使用Instant代替Date,LocalDateTime代替Calendar,DateTimeFormatter代替SimpleDateFormat

8.多线程并行处理定时任务

多线程并行处理定时任务时,Timer运行多个TimeTask时,只要其中之一没有捕获抛出的异常,其它任务便会自动终止运行,使用ScheduledExecutorService则没有这个问题

9.多线程count++操作

volatile解决多线程内存不可见问题。对于一写多读,是可以解决变量同步问题,但是如果多写,同样无法解决线程安全问题。
说明:如果是count++操作,使用如下类实现:AtomicInteger count = new AtomicInteger(); count.addAndGet(1); 如果是JDK8,推荐使用LongAdder对象,比AtomicLong性能更好(减少乐观锁的重试次数)。

10.集合初始化时,指定集合初始值大小

说明:HashMap使用HashMap(int initialCapacity) 初始化,如果暂时无法确定集合大小,那么指定默认值(16)即可。
正例:initialCapacity = (需要存储的元素个数 / 负载因子) + 1。注意负载因子(即loader factor)默认为0.75,如果暂时无法确定初始值大小,请设置为16(即默认值)。
反例: HashMap需要放置1024个元素,由于没有设置容量初始大小,随着元素增加而被迫不断扩容,resize()方法总共会调用8次,反复重建哈希表和数据迁移。当放置的集合元素个数达千万级时会影响程序性能。

HashMap在容量不够进行resize时由于高并发可能出现死链,导致CPU飙升,在开发过程中注意规避此风险。

11.在高并发场景中,避免使用”等于”判断作为中断或退出的条件。

说明:如果并发控制没有处理好,容易产生等值判断被“击穿”的情况,使用大于或小于的区间判断条件来代替。
反例:判断剩余奖品数量等于0时,终止发放奖品,但因为并发处理错误导致奖品数量瞬间变成了负数,这样的话,活动无法终止。

12.对于需要使用超大整数的场景,服务端一律使用String字符串类型返回,禁止使用Long类型。

说明:Java服务端如果直接返回Long整型数据给前端,JS会自动转换为Number类型(注:此类型为双精度浮点数,表示原理与取值范围等同于Java中的Double)。Long类型能表示的最大值是2的63次方-1,在取值范围之内,超过2的53次方 (9007199254740992)的数值转化为JS的Number时,有些数值会有精度损失。扩展说明,在Long取值范围内,任何2的指数次整数都是绝对不会存在精度损失的,所以说精度损失是一个概率问题。若浮点数尾数位与指数位空间不限,则可以精确表示任何整数,但很不幸,双精度浮点数的尾数位只有52位。

反例:通常在订单号或交易号大于等于16位,大概率会出现前后端单据不一致的情况,比如,“orderId”: 362909601374617692,前端拿到的值却是: 362909601374617660。

13.HTTP请求通过URL传递参数时,不能超过2048字节

说明:不同浏览器对于URL的最大长度限制略有不同,并且对超出最大长度的处理逻辑也有差异,2048字节是取所有浏览器的最小值。

14.HTTP请求通过body传递内容时,必须控制长度,超出最大长度后,后端解析会出错

说明:nginx默认限制是1MB,tomcat默认限制为2MB,当确实有业务需要传较大内容时,可以通过调大服务器端的限制。

15.页面重定向

服务器内部重定向必须使用forward;外部重定向地址必须使用URL统一代理模块生成,否则会因线上采用HTTPS协议而导致浏览器提示“不安全”,并且还会带来URL维护不一致的问题。

16.Math.random()

注意 Math.random() 这个方法返回是double类型,注意取值的范围 0≤x<1(能够取到零值,注意除零异常),如果想获取整数类型的随机数,不要将x放大10的若干倍然后取整,直接使用Random对象的nextInt或者nextLong方法。

17.任何数据结构的构造或初始化,都应指定大小,避免数据结构无限增长吃光内存。

18.Java 类库中定义的可以通过预检查方式规避的RuntimeException异常不应该通过catch 的方式来处理

Java 类库中定义的可以通过预检查方式规避的RuntimeException异常不应该通过catch 的方式来处理,比如:NullPointerException,IndexOutOfBoundsException等等。 说明:无法通过预检查的异常除外,比如,在解析字符串形式的数字时,可能存在数字格式错误,不得不通过catch NumberFormatException来实现。
正例:if (obj != null) {…}
反例:try { obj.method(); } catch (NullPointerException e) {…}

19.不要在finally块中使用return

说明:try块中的return语句执行成功后,并不马上返回,而是继续执行finally块中的语句,如果此处存在return语句,则在此直接返回,无情丢弃掉try块中的返回点。

20.根据国家法律,网络运行状态、网络安全事件、个人敏感信息操作等相关记录,留存的日志不少于六个月,并且进行网络多机备份。

21.生产环境禁止直接使用System.out 或System.err 输出日志或使用e.printStackTrace()打印异常堆栈。

22.异常信息应该包括两类信息:案发现场信息和异常堆栈信息。如果不处理,那么通过关键字throws往上抛出。

正例:logger.error(“inputParams:{} and errorMessage:{}”, 各类参数或者对象toString(), e.getMessage(), e);

23.MYSQL主键索引命名

主键索引名为pk_字段名;唯一索引名为uk_字段名;普通索引名则为idx_字段名。 说明:pk_ 即primary key;uk_ 即 unique key;idx_ 即index的简称。

24.MySQL过长字段

varchar是可变长字符串,不预先分配存储空间,长度不要超过5000,如果存储长度大于此值,定义字段类型为text,独立出来一张表,用主键来对应,避免影响其它字段索引效率。

25.表必备三字段:id, create_time, update_time。

其中id必为主键,类型为bigint unsigned、单表时自增、步长为1。create_time, update_time的类型均为datetime类型,前者现在时表示主动式创建,后者过去分词表示被动式更新。

26.单表行数超过500万行或者单表容量超过2GB,才推荐进行分库分表

说明:如果预计三年后的数据量根本达不到这个级别,请不要在创建表时就分库分表。

27.利用延迟关联或者子查询优化超多分页场景

说明:MySQL并不是跳过offset行,而是取offset+N行,然后返回放弃前offset行,返回N行,那当offset特别大的时候,效率就非常的低下,要么控制返回的总页数,要么对超过特定阈值的页数进行SQL改写。

正例:先快速定位需要获取的id段,然后再关联: SELECT t1.* FROM 表1 as t1, (select id from 表1 where 条件 LIMIT 100000,20 ) as t2 where t1.id=t2.id

28.SQL性能优化的目标

SQL性能优化的目标:至少要达到 range 级别,要求是ref级别,如果可以是consts最好。
说明:
1) consts 单表中最多只有一个匹配行(主键或者唯一索引),在优化阶段即可读取到数据。
2) ref 指的是使用普通的索引(normal index)。
3) range 对索引进行范围检索。

反例:explain表的结果,type=index,索引物理文件全扫描,速度非常慢,这个index级别比较range还低,与全表扫描是小巫见大巫。

29.如果需要存储表情,那么选择utf8mb4来进行存储,注意它与utf8编码的区别。

30.POJO类的布尔属性不能加is,而数据库字段必须加is_,要求在resultMap中进行字段与属性之间的映射。

31.不要用resultClass当返回参数,即使所有类属性名与数据库字段一一对应,也需要定义;反过来,每一个表也必然有一个与之对

32.分层领域模型规约

• DO(Data Object):此对象与数据库表结构一一对应,通过DAO层向上传输数据源对象。
• DTO(Data Transfer Object):数据传输对象,Service或Manager向外传输的对象。
• BO(Business Object):业务对象,可以由Service层输出的封装业务逻辑的对象。
• Query:数据查询对象,各层接收上层的查询请求。注意超过2个参数的查询封装,禁止使用Map类来传输。
• VO(View Object):显示层对象,通常是Web向模板渲染引擎层传输的对象。

33.二方库依赖

(1)【强制】定义GAV遵从以下规则:

1) GroupID格式:com.{公司/BU }.业务线 [.子业务线],最多4级。
说明:{公司/BU} 例如:alibaba/taobao/tmall/aliexpress等BU一级;子业务线可选。
正例:com.taobao.jstorm 或 com.alibaba.dubbo.register

2) ArtifactID格式:产品线名-模块名。语义不重复不遗漏,先到中央仓库去查证一下。
正例:dubbo-client / fastjson-api / jstorm-tool

3) Version:详细规定参考下方。

(2).二方库版本号命名方式:主版本号.次版本号.修订号

1)主版本号:产品方向改变,或者大规模API不兼容,或者架构不兼容升级。
2) 次版本号:保持相对兼容性,增加主要功能特性,影响范围极小的API不兼容修改。
3) 修订号:保持完全兼容性,修复BUG、新增次要功能特性等。

说明:注意起始版本号必须为:1.0.0,而不是0.0.1。

(3).如果依赖其它二方库

如果依赖其它二方库,尽量是provided引入,让二方库使用者去依赖具体版本号

34.服务器配置

(1).高并发服务器建议调小TCP协议的time_wait超时时间

说明:操作系统默认240秒后,才会关闭处于time_wait状态的连接,在高并发访问下,服务器端会因为处于time_wait的连接数太多,可能无法建立新的连接,所以需要在服务器上调小此等待值。

正例:在linux服务器上请通过变更/etc/sysctl.conf文件去修改该缺省值(秒): net.ipv4.tcp_fin_timeout = 30

(2).调大服务器所支持的最大文件句柄数(File Descriptor,简写为fd)

主流操作系统的设计是将TCP/UDP连接采用与文件一样的方式去管理,即一个连接对应于一个fd。主流的linux服务器默认所支持最大fd数量为1024,当并发连接数很大时很容易因为fd不足而出现“open too many files”错误,导致新的连接无法建立。建议将linux服务器所支持的最大句柄数调高数倍(与服务器的内存数量相关)。

(3).给JVM环境参数设置-XX:+HeapDumpOnOutOfMemoryError参数,让JVM碰到OOM场景时输出dump信息

OOM的发生是有概率的,甚至相隔数月才出现一例,出错时的堆内信息对解决问题非常有帮助

(4).在线上生产环境,JVM的Xms和Xmx设置一样大小的内存容量,避免在GC 后调整堆大小带来的压力
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值