多线程 N 次写文件
Last updated
Last updated
记一次项目中多线程 N 次写文件的愚蠢做法,通过这次愚蠢的编码,从中体会到的就是我们需要对 JDK 里面源码尽量熟悉,多看源码,这样才能提高我们编码的性能。
愚蠢代码如下:
上述代码封装了一个通用的多线程 N 次追加写文件的类,上述代码虽然可以保证完成任务,但是代码是非常低效。我发现这段代码的问题,也是因为,一开始我在项目里面只需要使用这段代码写一个文件,写入的次数是大概是在 1500 次左右;而后续由于功能需求增加,我需要使用这段代码写多个文件,每个文件写入次数都是 1500 次左右,从而项目运行的效率变得异常缓慢,如龟速运行,让我无法接受。
于是我开始改进,首先,我觉得每次写入的时候都去 new BufferedWriter 实例,这个是不可取的;浪费了 new 对象的时间,其实我们写文件,BufferedWriter 对象 new 一次就可以了。改进代码如下:
经过上述代码改进后,代码效率基本可以了,但是由于对源码不熟悉,如果专业的人看到这段代码,会觉得我们比较业余,因为那个 synchronized 是抢眼且多余的,在专业的人看来会非常的不舒服的。由于 IO 操作是我们日常编程中使用到最多的 API,但是我们却对源码是那么的不熟悉。
我们先来看看 Writer 的构造方法:
从以上源码可以看出,Writer 里面关键的流部分,都会有 lock 锁进行同步;所以,对于同一个 writer instance 是线程安全的;所以我们写同一个文件的时候使用同一个 writer instance 是线程安全的。也就是说我们使用的 Writer、FileWriter、BufferedWriter 是线程安全的。
具体的 write 方法源码分析如下:
在初始化 Writer Instance 的时候,我们会确定一个同步锁对象,所以只要我们使用的是一个 Writer 对象,则可以保证线程安全。
通过以上源码分析,我们可以很清楚地改进最优的代码如下:
通过以上三种方法进行测试,使用时间如下:
大家可以通过如下测试源码自行测试:
通过测试我们可以发现,确实是改进版本二的代码效率最高。
希望大家多看源码,了解 JDK 源码,学习优秀的编码方式。