关于java12:面试官你工作中做过-JVM-调优吗怎么做的

最近很多小伙伴跟我说,本人学了不少JVM的调优常识,然而在理论工作中却不晓得何时对JVM进行调优。明天,我就为大家介绍几种JVM调优的场景。 在浏览本文时,假设大家曾经理解了运行时的数据区域和罕用的垃圾回收算法,也理解了Hotspot反对的垃圾回收器。cpu占用过高cpu占用过高要分状况探讨,是不是业务上在搞流动,忽然有少量的流量进来,而且流动完结后cpu占用率就降落了,如果是这种状况其实能够不必太关怀,因为申请越多,须要解决的线程数越多,这是失常的景象。话说回来,如果你的服务器配置自身就差,cpu也只有一个外围,这种状况,略微多一点流量就真的可能把你的cpu资源耗尽,这时应该思考先把配置晋升吧。 第二种状况,cpu占用率长期过高,这种状况下可能是你的程序有那种循环次数超级多的代码,甚至是呈现死循环了。排查步骤如下: (1)用top命令查看cpu占用状况 这样就能够定位出cpu过高的过程。在linux下,top命令取得的过程号和jps工具取得的vmid是雷同的: (2)用top -Hp命令查看线程的状况 能够看到是线程id为7287这个线程始终在占用cpu (3)把线程号转换为16进制 [[email protected] ~]# printf "%x" 72871c77记下这个16进制的数字,上面咱们要用 (4)用jstack工具查看线程栈状况 [[email protected] ~]# jstack 7268 | grep 1c77 -A 10"http-nio-8080-exec-2" #16 daemon prio=5 os_prio=0 tid=0x00007fb66ce81000 nid=0x1c77 runnable [0x00007fb639ab9000] java.lang.Thread.State: RUNNABLE at com.spareyaya.jvm.service.EndlessLoopService.service(EndlessLoopService.java:19) at com.spareyaya.jvm.controller.JVMController.endlessLoop(JVMController.java:30) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190) at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138) at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105)通过jstack工具输入当初的线程栈,再通过grep命令联合上一步拿到的线程16进制的id定位到这个线程的运行状况,其中jstack前面的7268是第(1)步定位到的过程号,grep前面的是(2)、(3)步定位到的线程号。 从输入后果能够看到这个线程处于运行状态,在执行com.spareyaya.jvm.service.EndlessLoopService.service这个办法,代码行号是19行,这样就能够去到代码的19行,找到其所在的代码块,看看是不是处于循环中,这样就定位到了问题。 死锁死锁并没有第一种场景那么显著,web利用必定是多线程的程序,它服务于多个申请,程序产生死锁后,死锁的线程处于期待状态(WAITING或TIMED_WAITING),期待状态的线程不占用cpu,耗费的内存也很无限,而体现上可能是申请没法进行,最初超时了。在死锁状况不多的时候,这种状况不容易被发现。 能够应用jstack工具来查看 (1)jps查看java过程 [[email protected] ~]# jps -l8737 sun.tools.jps.Jps8682 jvm-0.0.1-SNAPSHOT.jar(2)jstack查看死锁问题 因为web利用往往会有很多工作线程,特地是在高并发的状况下线程数更多,于是这个命令的输入内容会非常多。jstack最大的益处就是会把产生死锁的信息(蕴含是什么线程产生的)输入到最初,所以咱们只须要看最初的内容就行了 Java stack information for the threads listed above:==================================================="Thread-4": at com.spareyaya.jvm.service.DeadLockService.service2(DeadLockService.java:35) - waiting to lock <0x00000000f5035ae0> (a java.lang.Object) - locked <0x00000000f5035af0> (a java.lang.Object) at com.spareyaya.jvm.controller.JVMController.lambda$deadLock$1(JVMController.java:41) at com.spareyaya.jvm.controller.JVMController$$Lambda$457/1776922136.run(Unknown Source) at java.lang.Thread.run(Thread.java:748)"Thread-3": at com.spareyaya.jvm.service.DeadLockService.service1(DeadLockService.java:27) - waiting to lock <0x00000000f5035af0> (a java.lang.Object) - locked <0x00000000f5035ae0> (a java.lang.Object) at com.spareyaya.jvm.controller.JVMController.lambda$deadLock$0(JVMController.java:37) at com.spareyaya.jvm.controller.JVMController$$Lambda$456/474286897.run(Unknown Source) at java.lang.Thread.run(Thread.java:748)Found 1 deadlock.发现了一个死锁,起因也高深莫测。 ...

October 6, 2022 · 2 min · jiezi

关于java12:聊聊数据库建表的15个小技巧

前言对于后端开发同学来说,拜访数据库,是代码中必不可少的一个环节。 零碎中收集到用户的外围数据,为了安全性,咱们个别会存储到数据库,比方:mysql,oracle等。 后端开发的日常工作,须要一直的建库和建表,来满足业务需要。 通常状况下,建库的频率比建表要低很多,所以,咱们这篇文章次要探讨建表相干的内容。 如果咱们在建表的时候不留神细节,等前面零碎上线之后,表的保护老本变得十分高,而且很容易踩坑。 明天就跟大家一起聊聊,数据库建表的15个小技巧,心愿对你会有所帮忙 1.名字建表的时候,给表、字段和索引起个好名字,真的太重要了。 1.1 见名知意名字就像表、字段和索引的一张脸,能够给人留下第一印象。 好的名字,长篇累牍,见名知意,让人情绪愉悦,可能进步沟通和保护老本。 坏的名字,模仿两可,不知所云。而且显得横七竖八,看得让人抓狂。 反例: 用户名称字段定义成:yong_hu_ming、用户_name、name、user_name_123456789你看了可能会一脸懵逼,这是什么骚操作? 正例: 用户名称字段定义成:user_name舒适揭示一下,名字也不宜过长,尽量管制在30个字符以内。1.2 大小写名字尽量都用小写字母,因为从视觉上,小写字母更容易让人读懂。 反例: 字段名:PRODUCT_NAME、PRODUCT_name全副大写,看起来有点不太直观。而一部分大写,一部分小写,让人看着更不爽。 正例: 字段名:product_name名字还是应用全小写字母,看着更难受。 1.3 分隔符很多时候,名字为了让人好了解,有可能会蕴含多个单词。 那么,多个单词间的分隔符该用什么呢? 反例: 字段名:productname、productName、product name、product@name单词间没有分隔,或者单词间用驼峰标识,或者单词间用空格分隔,或者单词间用@分隔,这几种形式都不太倡议。 正例: 字段名:product_name强烈建议大家在单词间用_分隔。 1.4 表名对于表名,在长篇累牍,见名知意的根底之上,倡议带上业务前缀。 如果是订单相干的业务表,能够在表名后面加个前缀:order_。 例如:order_pay、order_pay_detail等。 如果是商品相干的业务表,能够在表名后面加个前缀:product_。 例如:product_spu,product_sku等。 这样做的益处是为了不便归类,把雷同业务的表,能够十分疾速的汇集到一起。 另外,还有有个益处是,如果哪天有非订单的业务,比方:金融业务,也须要建一个名字叫做pay的表,能够取名:finance_pay,就能十分轻松的辨别。 这样就不会呈现同名表的状况。 1.5 字段名称字段名称是开发人员施展空间最大,但也最容易产生凌乱的中央。 比方有些表,应用flag示意状态,另外的表用status示意状态。 能够对立一下,应用status示意状态。 如果一个表应用了另一个表的主键,能够在另一张表的名前面,加_id或_sys_no,例如: 在product_sku表中有个字段,是product_spu表的主键,这时候能够取名:product_spu_id或product_spu_sys_no。 还有创立工夫,能够对立成:create_time,批改工夫对立成:update_time。 删除状态固定为:delete_status。 其实还有很多公共字段,在不同的表之间,能够应用全局对立的命名规定,定义成雷同的名称,以便于大家好了解。 1.6 索引名在数据库中,索引有很多种,包含:主键、一般索引、惟一索引、联结索引等。 每张表的主键只有一个,个别应用:id或者sys_no命名。 一般索引和联结索引,其实是一类。在建设该类索引时,能够加ix_前缀,比方:ix_product_status。 惟一索引,能够加ux_前缀,比方:ux_product_code。 2.字段类型在设计表时,咱们在抉择字段类型时,可施展空间很大。 工夫格局的数据有:date、datetime和timestamp等等能够抉择。 字符类型的数据有:varchar、char、text等能够抉择。 数字类型的数据有:int、bigint、smallint、tinyint等能够抉择。 说实话,抉择很多,有时候是一件坏事,也可能是一件好事。 如何抉择一个适合的字段类型,变成了咱们不得不面对的问题。 如果字段类型选大了,比方:本来只有1-10之间的10个数字,后果选了bigint,它占8个字节。 其实,1-10之间的10个数字,每个数字1个字节就能保留,抉择tinyint更为适合。 这样会白白浪费7个字节的空间。 如果字段类型择小了,比方:一个18位的id字段,抉择了int类型,最终数据会保留失败。 所以抉择一个适合的字段类型,还是十分重要的一件事件。 以下准则能够参考一下: 尽可能抉择占用存储空间小的字段类型,在满足失常业务需要的状况下,从小到大,往上选。如果字符串长度固定,或者差异不大,能够抉择char类型。如果字符串长度差异较大,能够抉择varchar类型。是否字段,能够抉择bit类型。枚举字段,能够抉择tinyint类型。主键字段,能够抉择bigint类型。金额字段,能够抉择decimal类型。工夫字段,能够抉择timestamp或datetime类型。3.字段长度后面咱们曾经定义好了字段名称,抉择了适合的字段类型,接下来,须要重点关注的是字段长度了。 比方:varchar(20),biginit(20)等。 那么问题来了,varchar代表的是字节长度,还是字符长度呢? 答:在mysql中除了varchar和char是代表字符长度之外,其余的类型都是代表字节长度。 biginit(n) 这个n示意什么意思呢? ...

September 6, 2022 · 2 min · jiezi