你要如何衡量你的人生

坚持,努力,让好事发生

1、@Autowired注解是如何实现自动装配的?
2、当为类型为OrderService的Bean装配类型为UserService的属性时,如果此时Spring容器中存在多个类型为UserService的bean,此时Spring是如何处理的?
3、自动装配的模型是什么?有哪几种?和Autowired注解有什么关联?

@Autowired 自动装配是通过后置处理器来完成的。这个后置处理器就是 AutowiredAnnotationBeanPostProcessor

阅读全文 »

思考几个问题
如果没有Spring,我们怎么开发维护Java Web代码
Spring的核心功能有哪些?
Spring Bean是怎么被创建的呢?

(1) spring IoC是什么

IoC全称Inversion of Control,直译为控制反转。
IoC是一种思想,可以用来设计出低耦合、易扩展的代码。

就好比以前租房子时自己按照要求一个一个找房东,现在可以把要求告诉房屋中介通过他们找房子。
get-instance-direct

像房屋卧室大小、朝向、位置、价格、家具这些要求全部交给房屋中介去搞定。

get-instance-by-ioc-container

在Java Web开发时,我们经常也会有类似的问题,在创建对象时会有很多字段/状态/要求,可能会发生变更,导致需要改大量简单但是重复的代码,而且可能对线上的服务产生影响,需要研发、测试回归,造成大量的人力资源浪费。

阅读全文 »

遇到一个排序需求,按照数字、字母、汉字的顺序排序。

<!-- https://mvnrepository.com/artifact/com.ibm.icu/icu4j -->
<dependency>
    <groupId>com.ibm.icu</groupId>
    <artifactId>icu4j</artifactId>
    <version>4.8</version>
</dependency>

Collections.sort(datas, new Comparator<TestVo>() {
	@Override
	public int compare(TestVo o1, TestVo o2) {
		// 
		if (o1.getField1() == null) {
			return 1;
		} else if (o2.getField1() == null) {
			return -1;
		} else if (!o1.getField1().equals(o2.getField1())) {
			return com.ibm.icu.text.Collator.getInstance(com.ibm.icu.util.ULocale.SIMPLIFIED_CHINESE).compare(o1.getField1(), o2.getField1());
		}

		// 
		if (o1.getField2() == null) {
			return 1;
		} else if (o2.getField2() == null) {
			return -1;
		}
		if (!o1.getField2().equals(o2.getField2())) {
			return com.ibm.icu.text.Collator.getInstance(com.ibm.icu.util.ULocale.SIMPLIFIED_CHINESE).compare(o1.getField2(), o2.getField2());
		}

		// 
		if (o1.getField3() == null) {
			return 1;
		} else if (o2.getField3() == null) {
			return -1;
		}
		if (!o1.getField3().equals(o2.getField3())) {
			return com.ibm.icu.text.Collator.getInstance(com.ibm.icu.util.ULocale.SIMPLIFIED_CHINESE).compare(o1.getField3(), o2.getField3());
		}

		// 
		if (o1.geField4() == null) {
			return -1;
		} else if (o2.geField4() == null) {
			return 1;
		}
		if (!o1.geField4().equals(o2.geField4())) {
			return com.ibm.icu.text.Collator.getInstance(com.ibm.icu.util.ULocale.SIMPLIFIED_CHINESE).compare(o2.geField4(), o1.geField4());
		}

		return 0;
	}
});
		
阅读全文 »

这儿使用 用户 - 群组 举例。(可以认为是QQ用户和QQ群的关系)
一个用户有多个群组,一个群组有多个用户,用户和群组是多对多关系。

这儿使用OrientDb官方自带的etl rdbms导入数据。
吐槽:OrientDb ETL 工具 对多对多的关系支持不好,还需要自己写代码处理。(总感觉OrientDb是程序员思维的产品,功能可以用)
Neo4j支持的就特别好,一个语句就解决了,瞬间感觉Neo4j好灵活。

1. 准备环境

下载MySQL的jar包放到OrientDb的lib目录下。
启动OrientDb
准备MySQL数据

阅读全文 »

beers.csv: contains the beer records
breweries.csv: contains the breweries records
breweries_geocode.csv: contains the geocodes of the breweries. This file is not used in this Tutorial
categories.csv: contains the beer categories
styles.csv: contains the beer styles

beers.csv:包含啤酒记录
breweries.csv:包含啤酒厂记录
breweries_geocode.csv:包含啤酒厂的地理编码。 本教程中未使用此文件
categories.csv:包含啤酒类别
styles.csv:包含啤酒风格

Nodes: Beer, Category, Style, Brewery;
Relationships: HasCategory, HasStyle, HasBrewery.

节点:啤酒,类别,风格,啤酒厂;
关系:有类别,有风格,有啤酒厂。

阅读全文 »

遇到问题第一反应,看监控,看报警,看日志,定位问题。
线上故障主要会包括 CPU、磁盘、内存以及网络问题。
看监控,先看机房有没有问题,然后看机房里的机器有问题,是CPU load高,磁盘IO高,内存不够用,还是网络不稳定。或者可以和历史监控做对比,找出异常情况。
如果找不出来,看日志吧,看看有没有异常信息。

** 如果多台机器出问题 **

  1. 一般情况下,线上出问题是内存问题居多,因为写代码的时候可能没想到所有情况,导致内存不够用,频繁gc,甚至OOM,通过监控、报警、日志 判断
  2. 网络问题,通过监控判断
  3. CPU问题
  4. 调用的其它服务出问题 (数据库 第三方接口)
  5. 某个机房容器全部挂掉 可能性较小

** 一台机器出问题 **

  1. 检查容器是否有问题,宿主机故障,容器故障,容器网络有问题
  2. 流量分布不均衡,导致某台机器流量比较多

把问题范围确定了以后,基本可以从 CPU、内存、IO(文件IO 网络IO) 来确认和解决问题。

CPU

用top命令查看整体情况,load值、cpu利用率 是否正常
如果load值正常,代表系统负载正常
如果load值异常,需要看是什么原因导致,需要进一步查看
如果CPU利用率正常,代表此时没有耗费CPU的操作
如果CPU利用率很高,需要分析是什么原因导致。

系统负载 代表单位时间内正在运行或等待的进程或线程数,代表了系统的繁忙程度。
CPU利用率 则代表单位时间内一个线程或进程实时占用CPU的百分比。

一个进程或者线程在运行时,未必都在实时的利用CPU的。

下面是top命令对应的样例

[wkq@VM_77_25_centos ~]$ top
top - 16:12:30 up 146 days, 22:27,  1 user,  load average: 84.71, 104.35, 113.82
Tasks:  19 total,   1 running,  18 sleeping,   0 stopped,   0 zombie
Cpu0  :  6.9%us,  9.0%sy,  0.0%ni, 40.9%id, 37.8%wa,  2.6%hi,  2.3%si,  0.5%st
Cpu1  :  6.1%us,  8.6%sy,  0.0%ni, 46.5%id, 35.5%wa,  1.0%hi,  1.6%si,  0.6%st
Cpu2  :  7.0%us,  9.1%sy,  0.0%ni, 41.7%id, 38.4%wa,  2.6%hi,  0.7%si,  0.5%st
Cpu3  :  6.5%us,  8.9%sy,  0.0%ni, 48.0%id, 34.6%wa,  1.0%hi,  0.4%si,  0.6%st
Cpu4  :  7.0%us,  9.0%sy,  0.0%ni, 42.2%id, 38.2%wa,  2.6%hi,  0.6%si,  0.5%st
Cpu5  :  6.6%us,  9.0%sy,  0.0%ni, 48.7%id, 33.8%wa,  1.0%hi,  0.3%si,  0.6%st
Cpu6  :  6.8%us,  8.9%sy,  0.0%ni, 42.7%id, 38.0%wa,  2.6%hi,  0.5%si,  0.5%st
Cpu7  :  6.5%us,  8.9%sy,  0.0%ni, 49.5%id, 33.3%wa,  1.0%hi,  0.3%si,  0.6%st
Cpu8  :  6.9%us,  9.0%sy,  0.0%ni, 42.9%id, 37.6%wa,  2.6%hi,  0.5%si,  0.5%st
Cpu9  :  6.5%us,  8.9%sy,  0.0%ni, 49.3%id, 33.2%wa,  1.0%hi,  0.5%si,  0.6%st
Cpu10 :  6.9%us,  9.0%sy,  0.0%ni, 43.2%id, 37.3%wa,  2.6%hi,  0.5%si,  0.5%st
Cpu11 :  6.5%us,  8.9%sy,  0.0%ni, 49.6%id, 32.9%wa,  1.0%hi,  0.4%si,  0.6%st
Cpu12 :  6.9%us,  8.9%sy,  0.0%ni, 43.4%id, 37.1%wa,  2.6%hi,  0.5%si,  0.5%st
Cpu13 :  6.6%us,  8.9%sy,  0.0%ni, 50.1%id, 32.4%wa,  1.0%hi,  0.4%si,  0.6%st
Cpu14 :  6.9%us,  8.9%sy,  0.0%ni, 43.7%id, 36.9%wa,  2.6%hi,  0.5%si,  0.5%st
Cpu15 :  6.7%us,  8.9%sy,  0.0%ni, 50.5%id, 31.9%wa,  1.0%hi,  0.3%si,  0.6%st
Cpu16 :  7.0%us,  8.9%sy,  0.0%ni, 43.9%id, 36.6%wa,  2.6%hi,  0.5%si,  0.5%st
Cpu17 :  6.6%us,  8.8%sy,  0.0%ni, 50.8%id, 31.8%wa,  1.0%hi,  0.4%si,  0.6%st
Cpu18 :  7.0%us,  8.8%sy,  0.0%ni, 44.2%id, 36.4%wa,  2.6%hi,  0.5%si,  0.5%st
Cpu19 :  6.6%us,  8.9%sy,  0.0%ni, 51.1%id, 31.5%wa,  1.0%hi,  0.2%si,  0.6%st
Cpu20 :  6.9%us,  8.8%sy,  0.0%ni, 44.4%id, 36.2%wa,  2.6%hi,  0.5%si,  0.5%st
Cpu21 :  6.6%us,  8.9%sy,  0.0%ni, 50.9%id, 31.7%wa,  1.0%hi,  0.3%si,  0.6%st
Cpu22 :  6.9%us,  8.8%sy,  0.0%ni, 44.6%id, 36.0%wa,  2.6%hi,  0.5%si,  0.5%st
Cpu23 :  6.6%us,  8.9%sy,  0.0%ni, 51.4%id, 31.2%wa,  1.0%hi,  0.2%si,  0.6%st
Cpu24 :  6.9%us,  8.8%sy,  0.0%ni, 44.8%id, 35.8%wa,  2.6%hi,  0.5%si,  0.5%st
Cpu25 :  6.6%us,  8.9%sy,  0.0%ni, 51.4%id, 31.2%wa,  1.0%hi,  0.2%si,  0.6%st
Cpu26 :  6.3%us,  8.2%sy,  0.0%ni, 51.5%id, 29.1%wa,  2.8%hi,  1.5%si,  0.6%st
Cpu27 :  6.1%us,  8.9%sy,  0.0%ni, 45.9%id, 37.3%wa,  1.0%hi,  0.2%si,  0.6%st
Mem:  49283096k total, 48746440k used,   536656k free,   206260k buffers
Swap:        0k total,        0k used,        0k free,  7044244k cached

   PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
     1 root      20   0  105m  212    0 S  0.0  0.0   0:00.08 sh
     8 root      20   0 66352 1244  500 S  0.0  0.0   0:00.00 sshd
    10 root      20   0  114m 1200  592 S  0.0  0.0  43:28.46 crond
[wkq@VM_77_25_centos ~]$

可以看到这是一个28核CPU,load average: 84.71, 104.35, 113.82
也就是说 最近1分钟系统平均负载是 84.71,最近5分钟系统平均负载是 104.35,最近15分钟系统平均负载是 113.82
可以看到负载比较高

系统平均负载高,一般是计算量大导致的,比如 大量计算(count++)、死循环、频繁往map里put需要计算hash、

[wkq@VM_77_25_centos ~]$ top
top - 16:02:17 up 69 days, 23:08,  1 user,  load average: 0.03, 0.03, 0.05
Tasks:  68 total,   2 running,  66 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.3 us,  0.3 sy,  0.0 ni, 99.0 id,  0.3 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  1883844 total,    75024 free,   430228 used,  1378592 buff/cache
KiB Swap:        0 total,        0 free,        0 used.  1266684 avail Mem 

  PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND                                                                                             
 3031 wkq       20   0 2692228 354060   4156 S  0.3 18.8 477:30.26 java                                                                                                
16414 root      20   0  612232  13740   2380 S  0.3  0.7  21:40.11 barad_agent                                                                                         
    1 root      20   0   41020   2900   1816 S  0.0  0.2   4:49.45 systemd                                                                                                                                                                              

从上面的信息可以看到 load average: 0.03, 0.03, 0.05
也就是说 最近1分钟系统平均负载是 0.03,最近5分钟系统平均负载是 0.03,最近15分钟系统平均负载是 0.05
可以看到 负载特别低

load 值

load average 代表 1分钟、5分钟、15分钟 的系统平均负载,从这三个数字,可以判断系统负荷是大还是小。
单核CPU,当CPU完全空闲的时候,平均负荷为0;当CPU工作量饱和的时候,平均负荷为1。
因此 load average 这三个数值越低,代表系统负荷越小。

单核CPU load值0.7比较合理
8核CPU load值 7 - 8 比较合理

如果电脑里只有一个CPU,把CPU看成一条单行桥,桥上只有一个车道,所有的车都必须从这个桥上通过。那么
系统负荷为0,代表桥上一辆车也没有
系统负荷0.5,意味着桥上一半路段上有车
系统负荷1,意味着桥上道路已经被车占满
系统负荷1.7,代表着在桥上车子已经满了(100%),同时还有70%的车子在等待从桥上通过

查找CPU使用率高的线程

[wkq@VM_77_25_centos log]$ jps -l
147 org.springframework.boot.loader.PropertiesLauncher
361773 sun.tools.jps.Jps
[wkq@VM_77_25_centos log]$
[wkq@VM_77_25_centos log]$ top -p 147 -H
top - 20:29:01 up 798 days,  3:59,  3 users,  load average: 17.93, 17.65, 16.52
Tasks: 363 total,   5 running, 358 sleeping,   0 stopped,   0 zombie
Cpu(s): 14.6%us,  4.5%sy,  0.1%ni, 72.7%id,  5.9%wa,  0.0%hi,  2.2%si,  0.0%st
Mem:  527951688k total, 388728604k used, 139223084k free,  1940564k buffers
Swap: 16777212k total,      792k used, 16776420k free, 149503456k cached

   PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
   399 admin     20   0 25.5g 657m  15m S  4.3  0.1   1:02.00 java
   396 admin     20   0 25.5g 657m  15m R  2.7  0.1   0:37.58 java
   398 admin     20   0 25.5g 657m  15m S  2.7  0.1   0:37.39 java
   395 admin     20   0 25.5g 657m  15m S  2.3  0.1   0:34.83 java
   397 admin     20   0 25.5g 657m  15m S  2.3  0.1   0:34.69 java
   160 admin     20   0 25.5g 657m  15m S  2.0  0.1   0:46.18 java
   161 admin     20   0 25.5g 657m  15m S  2.0  0.1   0:46.11 java
   618 admin     20   0 25.5g 657m  15m S  1.3  0.1   0:11.01 java
   624 admin     20   0 25.5g 657m  15m S  1.3  0.1   0:11.13 java
   645 admin     20   0 25.5g 657m  15m S  1.3  0.1   0:11.05 java
   658 admin     20   0 25.5g 657m  15m S  1.3  0.1   0:11.13 java
   715 admin     20   0 25.5g 657m  15m S  1.3  0.1   0:11.10 java
   727 admin     20   0 25.5g 657m  15m S  1.3  0.1   0:10.96 java
   745 admin     20   0 25.5g 657m  15m S  1.3  0.1   0:11.15 java
   293 admin     20   0 25.5g 657m  15m S  1.0  0.1 149:24.83 java
   580 admin     20   0 25.5g 657m  15m S  1.0  0.1   0:10.95 java
   581 admin     20   0 25.5g 657m  15m S  1.0  0.1   0:10.90 java
   584 admin     20   0 25.5g 657m  15m S  1.0  0.1   0:11.13 java
   592 admin     20   0 25.5g 657m  15m S  1.0  0.1   0:11.08 java
   593 admin     20   0 25.5g 657m  15m S  1.0  0.1   0:10.92 java
   594 admin     20   0 25.5g 657m  15m S  1.0  0.1   0:11.00 java
   598 admin     20   0 25.5g 657m  15m S  1.0  0.1   0:11.01 java
   604 admin     20   0 25.5g 657m  15m S  1.0  0.1   0:11.14 java
   605 admin     20   0 25.5g 657m  15m S  1.0  0.1   0:10.98 java
   607 admin     20   0 25.5g 657m  15m S  1.0  0.1   0:10.97 java
   610 admin     20   0 25.5g 657m  15m S  1.0  0.1   0:11.03 java
   611 admin     20   0 25.5g 657m  15m S  1.0  0.1   0:11.20 java
   622 admin     20   0 25.5g 657m  15m S  1.0  0.1   0:11.04 java
   625 admin     20   0 25.5g 657m  15m S  1.0  0.1   0:11.01 java
   626 admin     20   0 25.5g 657m  15m S  1.0  0.1   0:11.07 java
[wkq@VM_77_25_centos log]$

top -p pid -H 来找到 CPU 使用率比较高的一些线程
-p用于指定进程
-H用于获取每个线程的信息

[wkq@VM_77_25_centos log]$ printf '%x\n' 399
18f
[wkq@VM_77_25_centos log]$
[wkq@VM_77_25_centos log]$  jstack 147 | grep 'nid=0x18f'
"XNIO-1 Accept" #114 prio=5 os_prio=0 tid=0x00007f1c06007000 nid=0x18f runnable [0x00007f1b3c97d000]
[wkq@VM_77_25_centos log]$
[wkq@VM_77_25_centos log]$

linux里nid用的是10进制,但是jstack里用的是16进制
将占用最高的 pid 转换为 16 进制 printf ‘%x\n’ ,根据pid得到nid

找到CPU占用的线程id后,为了确定这些是什么线程,需要使用 jstack 命令来查看这几个是什么线程。

jstack -l 13050 > stack.log

在 jstack 中找到相应的堆栈信息 grep 'nid' stack.log ,可以看到相对比较详细的线程信息。

cat jstack.log | grep "java.lang.Thread.State" | sort -nr | uniq -c 用来查看 WAITING 和 TIMED_WAITING 状态的线程。

内存

内存这块出问题的点会多一些,JVM参数配置,代码里未释放、线程池不合理、容器里线程复用导致内存未释放
但是绝大部分情况都是开发人员不合理使用或不合理配置导致

首先通过 top 命令 或者 free 命令查看内存使用情况
然后根据系统内存、JVM参数配置内存、实际使用内存、空闲内存 来判断是什么原因
这里需要排查问题的人了解 JVM运行时内存区域的划分,否则会找不到问题

查看空闲内存是否够用 (根据实际情况判断)
查看 JVM使用内存+堆外内存 是否超过系统内存,如果超过,JVM申请不到内存,服务一般会直接挂掉
查看JVM参数配置是否合理,可以通过 jstat 来辅助判断

通过jstat分析内存时,需要根据具体的垃圾回收器来分析,不同的垃圾回收器参数不一样。

[wkq@VM_77_25_centos ~]$ jstat -gc -h5 -t 13050  1000 10
Timestamp        S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT
       217492.5 8512.0 8512.0  0.0    77.3  68160.0  13154.8   963392.0   60728.2   77732.0 71386.5 11984.0 9862.9    133    2.921   8      0.947    3.868
       217493.7 8512.0 8512.0  0.0    77.3  68160.0  13154.8   963392.0   60728.2   77732.0 71386.5 11984.0 9862.9    133    2.921   8      0.947    3.868
       217494.7 8512.0 8512.0  0.0    77.3  68160.0  14055.9   963392.0   60728.2   77732.0 71386.5 11984.0 9862.9    133    2.921   8      0.947    3.868
       217495.7 8512.0 8512.0  0.0    77.3  68160.0  14055.9   963392.0   60728.2   77732.0 71386.5 11984.0 9862.9    133    2.921   8      0.947    3.868
       217496.7 8512.0 8512.0  0.0    77.3  68160.0  14055.9   963392.0   60728.2   77732.0 71386.5 11984.0 9862.9    133    2.921   8      0.947    3.868
Timestamp        S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT
       217497.7 8512.0 8512.0  0.0    77.3  68160.0  14055.9   963392.0   60728.2   77732.0 71386.5 11984.0 9862.9    133    2.921   8      0.947    3.868
       217498.7 8512.0 8512.0  0.0    77.3  68160.0  14055.9   963392.0   60728.2   77732.0 71386.5 11984.0 9862.9    133    2.921   8      0.947    3.868
       217499.7 8512.0 8512.0  0.0    77.3  68160.0  14055.9   963392.0   60728.2   77732.0 71386.5 11984.0 9862.9    133    2.921   8      0.947    3.868
       217500.7 8512.0 8512.0  0.0    77.3  68160.0  14055.9   963392.0   60728.2   77732.0 71386.5 11984.0 9862.9    133    2.921   8      0.947    3.868
       217501.7 8512.0 8512.0  0.0    77.3  68160.0  14068.0   963392.0   60728.2   77732.0 71386.5 11984.0 9862.9    133    2.921   8      0.947    3.868
[wkq@VM_77_25_centos ~]$
[wkq@VM_77_25_centos ~]$ jstat -gcutil -h5 -t 13050  1000 10
Timestamp         S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT
       217569.9   0.00   0.91  23.55   6.30  91.84  82.30    133    2.921     8    0.947    3.868
       217570.9   0.00   0.91  23.55   6.30  91.84  82.30    133    2.921     8    0.947    3.868
       217571.9   0.00   0.91  23.55   6.30  91.84  82.30    133    2.921     8    0.947    3.868
       217572.9   0.00   0.91  23.55   6.30  91.84  82.30    133    2.921     8    0.947    3.868
       217573.9   0.00   0.91  23.55   6.30  91.84  82.30    133    2.921     8    0.947    3.868
Timestamp         S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT
       217574.9   0.00   0.91  23.55   6.30  91.84  82.30    133    2.921     8    0.947    3.868
       217575.9   0.00   0.91  23.55   6.30  91.84  82.30    133    2.921     8    0.947    3.868
       217576.9   0.00   0.91  23.55   6.30  91.84  82.30    133    2.921     8    0.947    3.868
       217577.9   0.00   0.91  23.55   6.30  91.84  82.30    133    2.921     8    0.947    3.868
       217578.9   0.00   0.91  23.55   6.30  91.84  82.30    133    2.921     8    0.947    3.868
[wkq@VM_77_25_centos ~]$

网络IO

还是先看监控
网络层面的问题一般都比较复杂,场景多,定位难

超时

磁盘IO

其它

  1. 看日志,定位是传参的问题,还是程序逻辑,还是代码里内存未释放。

  2. 重现问题

  3. 分析问题
    用 JMX JMC jvisualvm 查看Java服务在运行过程中的内存、GC、线程等信息。
    VisualVM是Sun的一个OpenJDK项目,它是集成了多个JDK命令工具的一个可视化工具,它主要用来监控JVM的运行情况,可以用它来查看和浏览Heap Dump、Thread Dump、内存对象实例情况、GC执行情况、CPU消耗以及类的装载情况,也可以使用它来创建必要信息的日志。

也可以使用jstat命令来堆Java堆内存的使用情况进行统计 pid 3031
jstat -gcutil 3031 1000 10

[wkq@VM_77_25_centos ~]$ jstat -gcutil 3031 1000 10 
  S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT   
  0.00 100.00  27.27  78.98  97.75  97.20    155    1.642     0    0.000    1.642
  0.00 100.00  27.27  78.98  97.75  97.20    155    1.642     0    0.000    1.642
  0.00 100.00  27.27  78.98  97.75  97.20    155    1.642     0    0.000    1.642
  0.00 100.00  27.27  78.98  97.75  97.20    155    1.642     0    0.000    1.642
  0.00 100.00  27.27  78.98  97.75  97.20    155    1.642     0    0.000    1.642
  0.00 100.00  27.27  78.98  97.75  97.20    155    1.642     0    0.000    1.642
  0.00 100.00  27.27  78.98  97.75  97.20    155    1.642     0    0.000    1.642
  0.00 100.00  27.27  78.98  97.75  97.20    155    1.642     0    0.000    1.642
  0.00 100.00  27.27  78.98  97.75  97.20    155    1.642     0    0.000    1.642
  0.00 100.00  27.27  78.98  97.75  97.20    155    1.642     0    0.000    1.642
YGC: 从启动到采样时Young Generation GC的次数
YGCT: 从启动到采样时Young Generation GC所用的时间 (s).
FGC: 从启动到采样时Old Generation GC的次数.
FGCT: 从启动到采样时Old Generation GC所用的时间 (s).
GCT: 从启动到采样时GC所用的总时间 (s).
阅读全文 »

思路:排列组合(不是穷举)出编辑距离为1的词语,假定用户输入是错误的,用贝叶斯公式计算编辑距离最小的那个词(假设是正确的词)的概率。
可以优化

阅读全文 »

遇到一个问题,Java里处理异常会有多慢。然后就自测+Google

曾经在给一个业务系统增加限流功能,使用的限流组件在流量超过阈值时,会直接抛异常,异常导致 CPU 占用率飙升。第一次遇到这样的情况,让我们不得不思考,异常怎么会对性能造成这么大的影响?
在消除了这些异常之后,代码运行速度与以前相比大幅提升。这让我们产生一种猜测,就是在代码里面使用异常会带来显著的性能开销。因为异常是错误情况处理的重要组成部分,摒弃是不太可能的,所以我们需要衡量异常处理对于性能影响,我们可以通过一个实验看看异常处理的对于性能的影响。

Java在处理异常时会 取操作栈中引用的异常对象
建立一个异常对象,是建立一个普通Object耗时的约20倍(实际上差距会比这个数字更大一些,因为循环也占用了时间,追求精确的读者可以再测一下空循环的耗时然后在对比前减掉这部分),而抛出、接住一个异常对象,所花费时间大约是建立异常对象的4倍。

下面的数据3个为一组,分别是 异常不作处理花费的时间异常只抛出花费的时间异常打印到日志花费的时间
用时 0.062 s
用时 0.094 s
用时 0.782 s

阅读全文 »

Queue接口继承自Collection接口,除了最基本的Collection的方法之外,它还支持额外的 添加删除检查 操作。

队列 Queue

Queue的方法概述(设计思想)如下:

方法 \ 形式 抛异常 返回特殊值
添加元素 add(e) offer(e)
删除元素 remove() poll()
检查元素 element() peek()

Queue源码

package java.util;

/**
 * 设计用于在处理前保存元素的集合。
 * 除了基本的收集操作外,队列还提供额外的插入、提取和检查操作。
 * 
 * 这些方法都有两种形式:一种是在操作失败时抛出异常,另一种是返回特殊值(null或false,取决于操作)。
 * 后一种形式的插入操作专门设计用于容量受限的队列实现;在大多数实现中,插入操作不会失败。
 * 
 * 队列通常(但不一定)以FIFO(先进先出)方式对元素进行排序。
 * 例外情况包括优先级队列
 * 
 * 该接口是Java集合框架的成员。
 */ 
public interface Queue<E> extends Collection<E> {


    /**
     * 如果可以在不违反容量限制的情况下立即将指定元素插入此队列,在成功时返回 true,
     * 如果当前没有可用空间则抛出 IllegalStateException。
     *
     * @param e 要添加的元素
     * @return 
     * @throws IllegalStateException 如果由于容量限制,此时无法添加元素
     * @throws ClassCastException 如果指定元素的类阻止将其添加到此队列中 
     * @throws NullPointerException 如果指定的元素为null,并且此队列不允许使用null元素 
     * @throws IllegalArgumentException  如果此元素的某些属性阻止将其添加到此队列中
     */
    boolean add(E e);

    /**
     * add(e) 的优化版
     * 在队列容量满了添加时不抛异常  
     * 其它和add(e)都一样
     */
    boolean offer(E e);

    /**
     * 检索并删除此队列的头部。
     * 队列为空会抛异常
     *
     * @return 队列头结点
     * @throws NoSuchElementException 如果队列为空
     */
    E remove();

    /**
     * 检索并删除此队列的头部,如果此队列为空,则返回 null。
     *
     * @return 队列头结点,队列为空时返回null
     */
    E poll();

    /**
     * 检索但不删除此队列的头部。
     * 如果此队列为空,抛异常 NoSuchElementException 。
     *
     * @return 队列头结点
     * @throws NoSuchElementException 如果队列为空
     */
    E element();

    /**
     * element()优化版
     * 
     * 检索但不删除此队列的头部,如果此队列为空,则返回 null。
     *
     * @return 队列头结点,队列为空时返回null
     */
    E peek();

}

双端队列 Deque

Deque方法概述

方法 \ 形式 (头结点)抛异常 (头节点)返回特殊值 (尾结点)抛异常 (尾结点)返回特殊值
添加元素 addFirst(e) offerFirst(e) addLast(e) offerLast(e)
移除元素 removeFirst() pollFirst() removeLast() pollLast()
检查元素 getFirst() peekFirst() getLast() peekLast()

Deque接口扩展了 Queue接口。当deque用作队列时,会产生FIFO(先进先出)行为。

队列 和 双端队列 方法对比

队列方法 等效 双端队列方法
add(e) addLast(e)
offer(e) offerLast(e)
remove() removeFirst()
poll() pollFirst()
element() getFirst()
peek() peekFirst()

双端队列也可以用作 LIFO(后进先出)堆栈。应优先使用此接口而不是旧的 Stack 类。
当双端队列用作堆栈时,从双端队列的开头推送和弹出元素。

Stack 方法等价于 Deque 方法
Stack和Deque方法的比较

栈方法 等效 双端队列方法
push(e) addFirst(e)
pop(e) removeFirst(e)
peek() getFirst()

Deque源码

package java.util;

/**
 * deque是“双端队列”的缩写
 * 支持在两端插入和移除元素的线性集合。
 */
public interface Deque<E> extends Queue<E> {

    /**
     * 在此双端队列的前面插入指定元素
     * 队列满了会抛异常 IllegalStateException
     */ 
    void addFirst(E e);

    /**
     * 在此双端队列末尾插入指定元素
     * 队列满了会抛异常 IllegalStateException
     */
    void addLast(E e);

    /**
     * 在此双端队列的前面插入指定元素
     * 队列满了会失败
     */ 
    boolean offerFirst(E e);

    /**
     * 在此双端队列末尾插入指定元素
     * 队列满了会失败
     */
    boolean offerLast(E e);

    /**
     * 移除首个元素
     * 
     * 队列为空抛异常 NoSuchElementException
     */ 
    E removeFirst();

    /**
     * 移除队列最后一个元素
     * 
     * 队列为空抛异常 NoSuchElementException
     */
    E removeLast();

    /**
     * 移除首个元素
     * 
     * 队列为空返回null
     */ 
    E pollFirst();

    /**
     * 移除最后一个元素
     * 
     * 队列为空返回null
     */
    E pollLast();

    /**
     * 检索但不删除此双端队列的第一个元素。
     * 
     * 队列为空抛异常 NoSuchElementException
     */ 
    E getFirst();

    /**
     * 检索但不删除此双端队列的最后一个元素。
     * 
     * 队列为空抛异常 NoSuchElementException
     */
    E getLast();

    /**
     * 检索但不删除此双端队列的第一个元素。
     * 
     * 队列为空返回null
     */
    E peekFirst();

    /**
     * 检索但不删除此双端队列的最后一个元素。
     * 
     * 队列为空返回null
     */ 
    E peekLast();

    /**
     * 从此双端队列中删除第一次出现的指定元素。
     * 如果双端队列不包含该元素,则它保持不变。
     */
    boolean removeFirstOccurrence(Object o);

    /**
     * 从此双端队列中删除最后一次出现的指定元素。
     * 如果双端队列不包含该元素,则它保持不变。
     */ 
    boolean removeLastOccurrence(Object o);


    // 队列方法

    boolean add(E e);

    boolean offer(E e);

    E remove();

    E poll();

    E element();

    E peek();
    
    boolean addAll(Collection<? extends E> c);
    
    // 栈方法

    /**
     * 将元素推送到此双端队列表示的堆栈上(队列头部)
     * 
     * 容量满了抛异常 IllegalStateException 
     * 
     * 等效于 addFirst
     */ 
    void push(E e);

    /**
     * 从双端队列表示的堆栈中弹出一个元素。换句话说,删除并返回此双端队列的第一个元素。
     * 
     * 队列为空抛异常  NoSuchElementException
     * 
     * 等效于 removeFirst()
     */ 
    E pop();


    // 集合方法

    /**
     * 从双端队列中删除第一次出现的指定元素。
     * 如果双端队列不包含该元素,则它保持不变。
     * 
     * 等效于 removeFirstOccurrence(Object)
     */ 
    boolean remove(Object o);

    /**
     * 如果此双端队列包含指定元素,则返回 true。
     */ 
    boolean contains(Object o);

    /**
     * 返回队列的长度
     */ 
    int size();

    /**
     * 以正确的顺序返回此双端队列中元素的迭代器。
     * 
     * 元素将按从第一个(头)到最后一个(尾)的顺序返回。
     */ 
    Iterator<E> iterator();

    /**
     * 以相反的顺序返回此双端队列中元素的迭代器。
     * 
     * 元素将按从最后(尾)到第一个(头)的顺序返回。
     */ 
    Iterator<E> descendingIterator();

}

参考资料

[1] Collection - Stack & Queue 源码解析

0%