首页
在线工具
搜索
1
使用Metrics指标度量工具监控Java应用程序性能(Gauges, Counters, Histograms, Meters和 Timers实例)
2
如何将Virtualbox和VMware虚拟机相互转换
3
Jumpserver的MFA配置
4
Kuboard与KubeSphere的区别:Kubernetes管理平台对比
5
Markdown正确使用姿势
杂谈与随笔
工具与效率
源码阅读
技术管理
运维
数据库
前端开发
后端开发
Search
标签搜索
Angular
Docker
Phabricator
SpringBoot
Java
Chrome
SpringSecurity
SpringCloud
DDD
Git
Mac
K8S
Kubernetes
ESLint
SSH
高并发
Eclipse
Javascript
Vim
Centos
Jonathan
累计撰写
86
篇文章
累计收到
0
条评论
首页
栏目
杂谈与随笔
工具与效率
源码阅读
技术管理
运维
数据库
前端开发
后端开发
页面
搜索到
4
篇与
的结果
2017-03-12
待运行稳定后GC之后用jmap抓取内存快照
1、待运行稳定后GC之后用jmap抓取内存快照 2、重新运行可能产生内存泄露的代码 3、GC到稳定之后再次抓取内存快照 4、对比2次快照就可知道了 java内存泄漏的定位与分析 1、为什么会发生内存泄漏 Java 如何检测内在泄漏呢?我们需要一些工具进行检测,并发现内存泄漏问题,不然很容易发生down机问题。 编写java程序最为方便的地方就是我们不需要管理内存的分配和释放,一切由jvm来进行处理,当java对象不再被应用时,等到堆内存不够用时,jvm会进行垃圾回收,清除这些对象占用的堆内存空间,如果对象一直被应用,jvm无法对其进行回收,创建新的对象时,无法从Heap中获取足够的内存分配给对象,这时候就会导致内存溢出。而出现内存泄露的地方,一般是不断的往容器中存放对象,而容器没有相应的大小限制或清除机制。容易导致内存溢出。 当服务器应用占用了过多内存的时候,如何快速定位问题呢?现在,Eclipse MAT的出现使这个问题变得非常简单。EclipseMAT是著名的SAP公司贡献的一个工具,可以在Eclipse网站下载到它,完全免费的。 要定位问题,首先你需要获取服务器jvm某刻内存快照。jdk自带的jmap可以获取内存某一时刻的快照,导出为dmp文件后,就可以用Eclipse MAT来分析了,找出是那个对象使用内存过多。 2、内存泄漏的现象: 常常地,程序内存泄漏的最初迹象发生在出错之后,在你的程序中得到一个OutOfMemoryError。这种典型的情况发生在产品环境中,而在那里,你希望内存泄漏尽可能的少,调试的可能性也达到最小。也许你的**测试**环境和产品的系统环境不尽相同,导致泄露的只会在产品中暴露。这种情况下,你需要一个低负荷的工具来监听和寻找内存泄漏。同时,你还需要把这个工具同你的系统联系起来,而不需要重新启动他或者机械化你的代码。也许更重要的是,当你做分析的时候,你需要能够同工具分离而使得系统不会受到干扰。 一个OutOfMemoryError常常是内存泄漏的一个标志,有可能应用程序的确用了太多的内存;这个时候,你既不能增加JVM的堆的数量,也不能改变你的程序而使得他减少内存使用。但是,在大多数情况下,一个OutOfMemoryError是内存泄漏的标志。一个解决办法就是继续监听GC的活动,看看随时间的流逝,内存使用量是否会增加,如果有,程序中一定存在内存泄漏。 3、发现内存泄漏 jstat -gc pid 可以显示gc的信息,查看gc的次数,及时间。 其中最后五项,分别是young gc的次数,young gc的时间,full gc的次数,full gc的时间,gc的总时间。 2.jstat -gccapacity pid 可以显示,VM内存中三代(young,old,perm)对象的使用和占用大小, 如:PGCMN显示的是最小perm的内存使用量,PGCMX显示的是perm的内存最大使用量, PGC是当前新生成的perm内存占用量,PC是但前perm内存占用量。 其他的可以根据这个类推, OC是old内纯的占用量。 3.jstat -gcutil pid 统计gc信息统计。 4.jstat -gcnew pid 年轻代对象的信息。 5.jstat -gcnewcapacity pid 年轻代对象的信息及其占用量。 6.jstat -gcold pid old代对象的信息。 7.stat -gcoldcapacity pid old代对象的信息及其占用量。 8.jstat -gcpermcapacity pid perm对象的信息及其占用量。 9.jstat -class pid 显示加载class的数量,及所占空间等信息。 10.jstat -compiler pid 显示VM实时编译的数量等信息。 11.stat -printcompilation pid 当前VM执行的信息。 一些术语的中文解释: S0C:年轻代中第一个survivor(幸存区)的容量 (字节) S1C:年轻代中第二个survivor(幸存区)的容量 (字节) S0U:年轻代中第一个survivor(幸存区)目前已使用空间 (字节) S1U:年轻代中第二个survivor(幸存区)目前已使用空间 (字节) EC:年轻代中Eden(伊甸园)的容量 (字节) EU:年轻代中Eden(伊甸园)目前已使用空间 (字节) OC:Old代的容量 (字节) OU:Old代目前已使用空间 (字节) PC:Perm(持久代)的容量 (字节) PU:Perm(持久代)目前已使用空间 (字节) YGC:从应用程序启动到采样时年轻代中gc次数 YGCT:从应用程序启动到采样时年轻代中gc所用时间(s) FGC:从应用程序启动到采样时old代(全gc)gc次数 FGCT:从应用程序启动到采样时old代(全gc)gc所用时间(s) GCT:从应用程序启动到采样时gc用的总时间(s) NGCMN:年轻代(young)中初始化(最小)的大小 (字节) NGCMX:年轻代(young)的最大容量 (字节) NGC:年轻代(young)中当前的容量 (字节) OGCMN:old代中初始化(最小)的大小 (字节) OGCMX:old代的最大容量 (字节) OGC:old代当前新生成的容量 (字节) PGCMN:perm代中初始化(最小)的大小 (字节) PGCMX:perm代的最大容量 (字节) PGC:perm代当前新生成的容量 (字节) S0:年轻代中第一个survivor(幸存区)已使用的占当前容量百分比 S1:年轻代中第二个survivor(幸存区)已使用的占当前容量百分比 E:年轻代中Eden(伊甸园)已使用的占当前容量百分比 O:old代已使用的占当前容量百分比 P:perm代已使用的占当前容量百分比 S0CMX:年轻代中第一个survivor(幸存区)的最大容量 (字节) S1CMX :年轻代中第二个survivor(幸存区)的最大容量 (字节) ECMX:年轻代中Eden(伊甸园)的最大容量 (字节) DSS:当前需要survivor(幸存区)的容量 (字节)(Eden区已满) TT:持有次数限制 MTT :最大持有次数限制 如果定位内存泄漏问题我一般使用如下命令: Jstat -gcutil15469 2500 70 [root@ssss logs]# jstat -gcutil 15469 1000 300 S0 S1 E O P YGC YGCT FGC FGCT GCT 0.00 1.46 26.54 4.61 30.14 35 0.872 0 0.000 0.872 0.00 1.46 46.54 4.61 30.14 35 0.872 0 0.000 0.872 0.00 1.46 47.04 4.61 30.14 35 0.872 0 0.000 0.872 0.00 1.46 65.19 4.61 30.14 35 0.872 0 0.000 0.872 0.00 1.46 67.54 4.61 30.14 35 0.872 0 0.000 0.872 0.00 1.46 87.54 4.61 30.14 35 0.872 0 0.000 0.872 0.00 1.46 88.03 4.61 30.14 35 0.872 0 0.000 0.872 1.48 0.00 5.56 4.62 30.14 36 0.874 0 0.000 0.874 1000 代表多久间隔显示一次, 100 代表显示一次。 S0 — Heap上的 Survivor space 0 区已使用空间的百分比 S1 — Heap上的 Survivor space 1 区已使用空间的百分比 E — Heap上的 Eden space 区已使用空间的百分比 O — Heap上的 Old space 区已使用空间的百分比 P — Perm space 区已使用空间的百分比 YGC — 从应用程序启动到采样时发生 Young GC 的次数 YGCT– 从应用程序启动到采样时 Young GC 所用的时间(单位秒) FGC — 从应用程序启动到采样时发生 Full GC 的次数 FGCT– 从应用程序启动到采样时 Full GC 所用的时间(单位秒) GCT — 从应用程序启动到采样时用于垃圾回收的总时间(单位秒) 如果有大量的FGC就要查询是否有内存泄漏的问题了,图中的FGC数量就比较大,并且执行时间较长,这样就会导致系统的响应时间较长,如果对jvm的内存设置较大,那么执行一次FGC的时间可能会更长。 如果为了更好的证明FGC对服务器性能的影响,我们可以使用**Java **visualVM来查看一下: 从上图可以发现执行FGC的情况,下午3:10分之前是没有FGC的,之后出现大量的FGC。 上图是jvm堆内存的使用情况,下午3:10分之前的内存回收还是比较合理,但是之后大量内存无法回收,最后导致内存越来越少,导致大量的full gc。 下面我们在看看大量full GC对服务器性能的影响,下面是我用loadrunner对我们项目进行压力测试相应时间的截图: 从图中可以发现有,在进行full GC后系统的相应时间有了明显的增加,点击率和吞吐量也有了明显的下降。所以java内存泄漏对系统性能的影响是不可忽视的。 3、定位内存泄漏 当然通过上面几种方法我们可以发现java的内存泄漏问题,但是作为一名合格的高级工程师,肯定不甘心就把这样的结论交给开发,当然这也的结论交给开发,开发也很难定位问题,为了更好的提供自己在公司的地位,我们必须给开发工程师提供更深入的测试结论,下面就来认识一下MemoryAnalyzer.exe。java内存泄漏检查工具利器。 首先我们必须对jvm的堆内存进行dump,只有拿到这个文件我们才能分析出jvm堆内存中到底存了些什么内容,到底在做什么? MemoryAnalyzer的用户我在这里就不一一说明了,我的博客里也有说明,下面就展示我测试的成功图: 其中深蓝色的部分就为内存泄漏的部分,java的堆内存一共只有481.5M而内存泄漏的部分独自占有了336.2M所以本次的内存泄漏很明显,那么我就来看看那个方法导致的内存泄漏: 从上图我们可以发现红线圈着的方法占用了堆内存的67.75%,如果能把这个测试结果交给开发,开发是不是应该很好定位呢。所以作为一名高级测试工程师,我们需要学习的东西太多。 虽然不确定一定是内存泄漏,但是可以准确的告诉开发问题出现的原因,有一定的说服力。
2017年03月12日
2017-03-12
Java8阅读笔记
懂得什么是行为参数化 http://www.tuicool.com/articles/yIv2Mjy 对比: 通过IntelliJ IDEA 2016.3 来更好使用Java 8的Stream API 归约 使用归约方法的有事和并行化: 相比于前面写的逐步迭代求和,使用reduce的好处在于,这里的迭代被内部迭代抽象掉了,这让内部实现得以选择并行执行reduce操作。而迭代式求和例子要更新共享变量sum,这不是那么容易并行化的。如果你加入了同步,很可能会发现线程竞争抵消了并行本应带来的性能提升! java8 策略模式重构:P192 例子:对输入的内容进行验证或者格式化(比如只包含小写字母或者数字)。 // 此接口实际是一个函数接口 public interface ValidationStrategy { boolean execute(String s); } // 两个实现类 public class IsAllLowerCase implements ValidationStrategy { public boolean execute(String s) { return s.matches("[a-z] +"); } } public class IsNumeric implements ValidationStrategy { public boolean execute(String s) { return s.matches("\\d+""); } } / / 定义一个类去使用 public class Validator{ private final ValidationStrategy strategy; public Validator(ValidationStrategy v){ this.strategy = v; } public boolean validate(String s){ return strategy.execute(s); } } // 实际业务中使用 Validator numericValidateor = new Validator(new IsNumeric()); boolean b1 = numericValidator.validate("aaaa"); Validator lowerCaseValidator = new Validator(new IsAllLowerCase()); boolean b2 = lowerCaseValidator.validate("bbbb"); 使用Lambda表达式: 不需要编写两个实现类直接使用Lambda表达式: Validator numericValidator = new Validator((String s) -> s.matches("[a-z]+")); boolean b1 = numericValidaor.validate("aaaa"); Validator lowerCaseValidator = new Validator((String s) -> s.matches("\\d+")); boolean b2 = lowerCaseValidator.validate("bbbb"); 引入Optional类的意图并非消除每一个null引用。 创建Optional对象 1.声明一个空的Optional Optional<Car> optCar = Optional.empty(); 2.依据一个非空值创建Optional Optional<Car> optCar = Optional.of(car);// 如果car是一个null,这段代码会立即抛出一个NullPointerException,而不是你访问car属性值时才返回一个错误。 3.可接受null的Optional Optional<Car> optCar = Optional.ofNullable(car); 如果car是null,那么得到的Optional对象就是个空对象。 两层Optional嵌套必须使用flatMap 如果你引用第三方库是需要序列化的,使用Optional可能会出错。 如果您返回的的是OptionalInt(基础类型)类型的对象,你就不能将其作为方法引用传递给另一个Optional对象的flatMap方法
2017年03月12日
2017-02-07
使用Metrics指标度量工具监控Java应用程序性能(Gauges, Counters, Histograms, Meters和 Timers实例)
Metrics是一个给JAVA服务的各项指标提供度量工具的包,在JAVA代码中嵌入Metrics代码,可以方便的对业务代码的各个指标进行监控,同时,Metrics能够很好的跟Ganlia、Graphite结合,方便的提供图形化接口。基本使用方式直接将core包(目前稳定版本3.0.1)导入pom文件即可,配置如下: <dependency> <groupId>com.codahale.metrics</groupId> <artifactId>metrics-core</artifactId> <version>3.0.1</version> </dependency> core包主要提供如下核心功能: Metrics Registries类似一个metrics容器,维护一个Map,可以是一个服务一个实例。 支持五种metric类型:Gauges、Counters、Meters、Histograms和Timers。 可以将metrics值通过JMX、Console,CSV文件和SLF4J loggers发布出来。 五种Metrics类型: Gauges Gauges是一个最简单的计量,一般用来统计瞬时状态的数据信息,比如系统中处于pending状态的job。测试代码 package com.netease.test.metrics; import com.codahale.metrics.ConsoleReporter; import com.codahale.metrics.Gauge; import com.codahale.metrics.JmxReporter; import com.codahale.metrics.MetricRegistry; import java.util.Queue; import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.TimeUnit; /** * User: hzwangxx * Date: 14-2-17 * Time: 14:47 * 测试Gauges,实时统计pending状态的job个数 */ public class TestGauges { /** * 实例化一个registry,最核心的一个模块,相当于一个应用程序的metrics系统的容器,维护一个Map */ private static final MetricRegistry metrics = new MetricRegistry(); private static Queue<String> queue = new LinkedBlockingDeque<String>(); /** * 在控制台上打印输出 */ private static ConsoleReporter reporter = ConsoleReporter.forRegistry(metrics).build(); public static void main(String[] args) throws InterruptedException { reporter.start(3, TimeUnit.SECONDS); //实例化一个Gauge Gauge<Integer> gauge = new Gauge<Integer>() { @Override public Integer getValue() { return queue.size(); } }; //注册到容器中 metrics.register(MetricRegistry.name(TestGauges.class, "pending-job", "size"), gauge); //测试JMX JmxReporter jmxReporter = JmxReporter.forRegistry(metrics).build(); jmxReporter.start(); //模拟数据 for (int i=0; i<20; i++){ queue.add("a"); Thread.sleep(1000); } } } /* console output: 14-2-17 15:29:35 =============================================================== -- Gauges ---------------------------------------------------------------------- com.netease.test.metrics.TestGauges.pending-job.size value = 4 14-2-17 15:29:38 =============================================================== -- Gauges ---------------------------------------------------------------------- com.netease.test.metrics.TestGauges.pending-job.size value = 6 14-2-17 15:29:41 =============================================================== -- Gauges ---------------------------------------------------------------------- com.netease.test.metrics.TestGauges.pending-job.size value = 9 */ 通过以上步骤将会向MetricsRegistry容器中注册一个名字为com.netease.test.metrics .TestGauges.pending-job.size的metrics,实时获取队列长度的指标。另外,Core包种还扩展了几种特定的Gauge: JMX Gauges—提供给第三方库只通过JMX将指标暴露出来。 Ratio Gauges—简单地通过创建一个gauge计算两个数的比值。 Cached Gauges—对某些计量指标提供缓存 Derivative Gauges—提供Gauge的值是基于其他Gauge值的接口。 Counter Counter是Gauge的一个特例,维护一个计数器,可以通过inc()和dec()方法对计数器做修改。使用步骤与Gauge基本类似,在MetricRegistry中提供了静态方法可以直接实例化一个Counter。 package com.netease.test.metrics; import com.codahale.metrics.ConsoleReporter; import com.codahale.metrics.Counter; import com.codahale.metrics.MetricRegistry; import java.util.LinkedList; import java.util.Queue; import java.util.concurrent.TimeUnit; import static com.codahale.metrics.MetricRegistry.*; /** * User: hzwangxx * Date: 14-2-14 * Time: 14:02 * 测试Counter */ public class TestCounter { /** * 实例化一个registry,最核心的一个模块,相当于一个应用程序的metrics系统的容器,维护一个Map */ private static final MetricRegistry metrics = new MetricRegistry(); /** * 在控制台上打印输出 */ private static ConsoleReporter reporter = ConsoleReporter.forRegistry(metrics).build(); /** * 实例化一个counter,同样可以通过如下方式进行实例化再注册进去 * pendingJobs = new Counter(); * metrics.register(MetricRegistry.name(TestCounter.class, "pending-jobs"), pendingJobs); */ private static Counter pendingJobs = metrics.counter(name(TestCounter.class, "pedding-jobs")); // private static Counter pendingJobs = metrics.counter(MetricRegistry.name(TestCounter.class, "pedding-jobs")); private static Queue<String> queue = new LinkedList<String>(); public static void add(String str) { pendingJobs.inc(); queue.offer(str); } public String take() { pendingJobs.dec(); return queue.poll(); } public static void main(String[]args) throws InterruptedException { reporter.start(3, TimeUnit.SECONDS); while(true){ add("1"); Thread.sleep(1000); } } } /* console output: 14-2-17 17:52:34 =============================================================== -- Counters -------------------------------------------------------------------- com.netease.test.metrics.TestCounter.pedding-jobs count = 4 14-2-17 17:52:37 =============================================================== -- Counters -------------------------------------------------------------------- com.netease.test.metrics.TestCounter.pedding-jobs count = 6 14-2-17 17:52:40 =============================================================== -- Counters -------------------------------------------------------------------- com.netease.test.metrics.TestCounter.pedding-jobs count = 9 */ 3. Meters Meters用来度量某个时间段的平均处理次数(request per second),每1、5、15分钟的TPS。比如一个service的请求数,通过metrics.meter()实例化一个Meter之后,然后通过meter.mark()方法就能将本次请求记录下来。统计结果有总的请求数,平均每秒的请求数,以及最近的1、5、15分钟的平均TPS。 package com.netease.test.metrics; import com.codahale.metrics.ConsoleReporter; import com.codahale.metrics.Meter; import com.codahale.metrics.MetricRegistry; import java.util.concurrent.TimeUnit; import static com.codahale.metrics.MetricRegistry.*; /** * User: hzwangxx * Date: 14-2-17 * Time: 18:34 * 测试Meters */ public class TestMeters { /** * 实例化一个registry,最核心的一个模块,相当于一个应用程序的metrics系统的容器,维护一个Map */ private static final MetricRegistry metrics = new MetricRegistry(); /** * 在控制台上打印输出 */ private static ConsoleReporter reporter = ConsoleReporter.forRegistry(metrics).build(); /** * 实例化一个Meter */ private static final Meter requests = metrics.meter(name(TestMeters.class, "request")); public static void handleRequest() { requests.mark(); } public static void main(String[] args) throws InterruptedException { reporter.start(3, TimeUnit.SECONDS); while(true){ handleRequest(); Thread.sleep(100); } } } /* 14-2-17 18:43:08 =============================================================== -- Meters ---------------------------------------------------------------------- com.netease.test.metrics.TestMeters.request count = 30 mean rate = 9.95 events/second 1-minute rate = 0.00 events/second 5-minute rate = 0.00 events/second 15-minute rate = 0.00 events/second 14-2-17 18:43:11 =============================================================== -- Meters ---------------------------------------------------------------------- com.netease.test.metrics.TestMeters.request count = 60 mean rate = 9.99 events/second 1-minute rate = 10.00 events/second 5-minute rate = 10.00 events/second 15-minute rate = 10.00 events/second 14-2-17 18:43:14 =============================================================== -- Meters ---------------------------------------------------------------------- com.netease.test.metrics.TestMeters.request count = 90 mean rate = 9.99 events/second 1-minute rate = 10.00 events/second 5-minute rate = 10.00 events/second 15-minute rate = 10.00 events/second */ Histograms Histograms主要使用来统计数据的分布情况,最大值、最小值、平均值、中位数,百分比(75%、90%、95%、98%、99%和99.9%)。例如,需要统计某个页面的请求响应时间分布情况,可以使用该种类型的Metrics进行统计。具体的样例代码如下: package com.netease.test.metrics; import com.codahale.metrics.ConsoleReporter; import com.codahale.metrics.Histogram; import com.codahale.metrics.MetricRegistry; import java.util.Random; import java.util.concurrent.TimeUnit; import static com.codahale.metrics.MetricRegistry.name; /** * User: hzwangxx * Date: 14-2-17 * Time: 18:34 * 测试Histograms */ public class TestHistograms { /** * 实例化一个registry,最核心的一个模块,相当于一个应用程序的metrics系统的容器,维护一个Map */ private static final MetricRegistry metrics = new MetricRegistry(); /** * 在控制台上打印输出 */ private static ConsoleReporter reporter = ConsoleReporter.forRegistry(metrics).build(); /** * 实例化一个Histograms */ private static final Histogram randomNums = metrics.histogram(name(TestHistograms.class, "random")); public static void handleRequest(double random) { randomNums.update((int) (random*100)); } public static void main(String[] args) throws InterruptedException { reporter.start(3, TimeUnit.SECONDS); Random rand = new Random(); while(true){ handleRequest(rand.nextDouble()); Thread.sleep(100); } } } /* 14-2-17 19:39:11 =============================================================== -- Histograms ------------------------------------------------------------------ com.netease.test.metrics.TestHistograms.random count = 30 min = 1 max = 97 mean = 45.93 stddev = 29.12 median = 39.50 75% <= 71.00 95% <= 95.90 98% <= 97.00 99% <= 97.00 99.9% <= 97.00 14-2-17 19:39:14 =============================================================== -- Histograms ------------------------------------------------------------------ com.netease.test.metrics.TestHistograms.random count = 60 min = 0 max = 97 mean = 41.17 stddev = 28.60 median = 34.50 75% <= 69.75 95% <= 92.90 98% <= 96.56 99% <= 97.00 99.9% <= 97.00 14-2-17 19:39:17 =============================================================== -- Histograms ------------------------------------------------------------------ com.netease.test.metrics.TestHistograms.random count = 90 min = 0 max = 97 mean = 44.67 stddev = 28.47 median = 43.00 75% <= 71.00 95% <= 91.90 98% <= 96.18 99% <= 97.00 99.9% <= 97.00 */ 5. Timers Timers主要是用来统计某一块代码段的执行时间以及其分布情况,具体是基于Histograms和Meters来实现的。样例代码如下: package com.netease.test.metrics; import com.codahale.metrics.ConsoleReporter; import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.Timer; import java.util.Random; import java.util.concurrent.TimeUnit; import static com.codahale.metrics.MetricRegistry.name; /** * User: hzwangxx * Date: 14-2-17 * Time: 18:34 * 测试Timers */ public class TestTimers { /** * 实例化一个registry,最核心的一个模块,相当于一个应用程序的metrics系统的容器,维护一个Map */ private static final MetricRegistry metrics = new MetricRegistry(); /** * 在控制台上打印输出 */ private static ConsoleReporter reporter = ConsoleReporter.forRegistry(metrics).build(); /** * 实例化一个Meter */ // private static final Timer requests = metrics.timer(name(TestTimers.class, "request")); private static final Timer requests = metrics.timer(name(TestTimers.class, "request")); public static void handleRequest(int sleep) { Timer.Context context = requests.time(); try { //some operator Thread.sleep(sleep); } catch (InterruptedException e) { e.printStackTrace(); } finally { context.stop(); } } public static void main(String[] args) throws InterruptedException { reporter.start(3, TimeUnit.SECONDS); Random random = new Random(); while(true){ handleRequest(random.nextInt(1000)); } } } /* 14-2-18 9:31:54 ================================================================ -- Timers ---------------------------------------------------------------------- com.netease.test.metrics.TestTimers.request count = 4 mean rate = 1.33 calls/second 1-minute rate = 0.00 calls/second 5-minute rate = 0.00 calls/second 15-minute rate = 0.00 calls/second min = 483.07 milliseconds max = 901.92 milliseconds mean = 612.64 milliseconds stddev = 196.32 milliseconds median = 532.79 milliseconds 75% <= 818.31 milliseconds 95% <= 901.92 milliseconds 98% <= 901.92 milliseconds 99% <= 901.92 milliseconds 99.9% <= 901.92 milliseconds 14-2-18 9:31:57 ================================================================ -- Timers ---------------------------------------------------------------------- com.netease.test.metrics.TestTimers.request count = 8 mean rate = 1.33 calls/second 1-minute rate = 1.40 calls/second 5-minute rate = 1.40 calls/second 15-minute rate = 1.40 calls/second min = 41.07 milliseconds max = 968.19 milliseconds mean = 639.50 milliseconds stddev = 306.12 milliseconds median = 692.77 milliseconds 75% <= 885.96 milliseconds 95% <= 968.19 milliseconds 98% <= 968.19 milliseconds 9
2017年02月07日
2016-09-19
Lombok 安装、入门 - 消除冗长的java代码
Lombok 安装、入门 - 消除冗长的java代码 前言 逛开源社区的时候无意发现的,用了一段时间,觉得还可以,特此推荐一下。lombok提供了简单的注解的形式来帮助我们简化消除一些必须有但显得很臃肿的java代码。特别是相对于POJO,光说不做不是我的风格,先来看看吧。 lombok的官方网址:http://projectlombok.org/ lombok其实到这里我就介绍完了,开个玩笑,其实官网上有lombok三分四十九秒的视频讲解,里面讲的也很清楚了,而且还有文档可以参考。在这里我就不扯太多,先来看一下lombok的安装,其实这个官网视频上也有讲到啦 lombok安装 使用lombok是需要安装的,如果不安装,IDE则无法解析lombok注解。先在官网下载最新版本的JAR包,现在是0.11.2版本,我用的是0.11.0。第一次使用的时候我下载的是最新版本的,也就是我现在用的0.11.0,到现在已经更新了两个版本,更新的好快啊...... 1. 双击下载下来的JAR包安装lombok 我选择这种方式安装的时候提示没有发现任何IDE,所以我没安装成功,我是手动安装的。如果你想以这种方式安装,请参考官网的视频。 2. eclipse / myeclipse手动安装 将lombok.jar复制到myeclipse.ini / eclipse.ini所在的文件夹目录下 打开eclipse.ini / myeclipse.ini,在最后面插入以下两行并保存: -Xbootclasspath/a:lombok.jar -javaagent:lombok.jar 重启eclipse / myeclipse lombok注解 lombok提供的注解不多,可以参考官方视频的讲解和官方文档。 Lombok注解在线帮助文档:http://projectlombok.org/features/index. 下面介绍几个我常用的lombok注解: @Data:注解在类上;提供类所有属性的getting和setting方法,此外还提供了equals、canEqual、hashCode、toString方法 @Setter:注解在属性上;为属性提供setting方法 @Getter:注解在属性上;为属性提供getting方法 @Log4j:注解在类上;为类提供一个属性名为log的log4j日志对象 @NoArgsConstructor:注解在类上;为类提供一个无参的构造方法 @AllArgsConstructor:注解在类上;为类提供一个全参的构造方法 下面是简单示例 1. 不使用lombok的方案 public class Person { private String id; private String name; private String identity; private Logger log = Logger.getLogger(Person.class); public Person() { } public Person(String id, String name, String identity) { this.id = id; this.name = name; this.identity = identity; } public String getId() { return id; } public String getName() { return name; } public String getIdentity() { return identity; } public void setId(String id) { this.id = id; } public void setName(String name) { this.name = name; } public void setIdentity(String identity) { this.identity = identity; } } 2. 使用lombok的方案 @Data @Log4j @NoArgsConstructor @AllArgsConstructor public class Person { private String id; private String name; private String identity; } 上面的两个java类,从作用上来看,它们的效果是一样的,相比较之下,很明显,使用lombok要简洁许多,特别是在类的属性较多的情况下,同时也避免了修改字段名字时候忘记修改方法名所犯的低级错误。最后需要注意的是,在使用lombok注解的时候记得要导入lombok.jar包到工程。
2016年09月19日