提交订单性能优化系列之005-单线程改为多线程,测试并发线程数与性能之间的关系
概括总结
“并发线程数量”与“每秒能提交的订单数量”之间并不是线性的关系,当达到某个临界值以后,线程的增加对性能的提升就不明显了,甚至会降低性能。至于“临界值”是多少,不同的电脑应该是不一样的。我这次测试的线程临界值是365左右。
005版本更新说明
- 把单线程改为多线程。
- 不同的线程数量需要分别来测试,有两种方式可以执行测试,第一种是把所有的测试写在同一个类中,用方法来区分,一开始也确实是这么做的。但是当前版本(5.3.0-M1)的JUnit并不支持按指定顺序执行测试用例,所以只好用第二种方式:写多个测试类,每个类中只执行一次测试。
- 修改了SQL语句,把商品的库存从100改成了10000。
- 修改了数据库允许的最大连接数,从2000改成了20000。这一步在代码里面没有体现,需要修改mysql数据库的配置文件(windows下是my.ini,Linux下是my.cnf)。备注:你可以先不改,等到报错“too many connections”的时候再改。
关于CountDownLatch
“CountDownLatch”作为Java术语如果翻译成中文叫做“倒计数锁存器”,如果只是作为普通的英文短语来翻译的话,我觉得应该叫“倒计时门闩”,再发散一点就是“倒计时开门”。
举例来说:现在有10匹马比赛,在开始比赛之前,马都分别关在各自的门房里,假设现在需要放这10匹马出来,有以下两种放法:
- 有1个负责人,听到口令枪响之后,从第1个门房飞快地跑到第10个门房,每经过一个门房就打开一扇门,放马出来。
- 有10个负责人分别把守着10扇门,听到口令枪响之后,同时打开这10扇门,放马出来。
显然第2种做法的“同时性”会比第一种做法的“同时性”要高(虽然第2种做法也无法绝对地保证“同时”,毕竟人和人的反应速度也不一样)
如果用Java代码来体现这两种差别,则第1种的伪代码是这样的:
int horseNumber = 10; // 10匹马
for (int i = 0; i < horseNumber; i++) {
new Thread(() -> {
// 放马出来
}).start();
}
第2种的伪代码是这样的:
int horseNumber = 10; // 10匹马
CountDownLatch startGate = new CountDownLatch(horseNumber);
for (int i = 0; i < horseNumber; i++) {
new Thread(() -> {
startGate.await(); // 此处省略try-catch代码
// 放马出来
}).start();
startGate.countDown();
}
第2种写法的“同时性”比第1种的高,而且线程数(即马匹数)越多,差别越明显。
“并发线程数量”与“每秒能提交的订单数量”之间的关系
这次测试的结果见下图(10次测试的平均值):
说明:横坐标的值是有规律的,都是以1.5倍增长的。
本来还想测试更多的线程数,但是数据库支撑不住了,一直报错,没找到解决办法。等以后解决了再测试更高的线程数。
【备注】:不同的机器上的测试结果会不一样,以上测试结果仅供参考。
源码
005版本的github源码在这里,如果不知道怎样运行项目,请参考这里
(转载本站文章请注明出处二胡1999 的个人技术博客www.erhu1999.com ,请勿用于任何商业用途)