`
langyu
  • 浏览: 883959 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

工作随笔2010/10/14(感悟,问题及学习)

阅读更多

        这段时间在Code Review之余负责一个处理大数据量程序的正常运行。本应该是国庆之前完成的事,但因对程序处理能力的认识不足就拖到了现在。程序由单线程改造为并发,并因此修改当初的设计,后来针对出现的问题做持续的处理及优化。下面列出在完成这个任务时所想到的及问题总结

1. 由使用并发看到的
        在处理大数据量任务时,可以做到的要么提高执行效率,要么并发执行。如果在单线程效率达到瓶颈时,不得不引入并发,并面对随之而来的问题。在我的程序中,多线程删除某个目录下的所有文件,或是多线程往同一文件中写数据,都得考虑同步时的争锁问题。
  • 线程数量有阈值,并不是越多越好。因应用而定,对共享的争用是需要权衡的。
  • 设置条件,减少多线程进入同步块的机会。如每条线程执行500条数据,才去检查共享目录的文件。
  • 在频繁出现资源争用的情况时,为不同线程设置不同的sleep时间,错开执行。

2. 持续优化可以确定的性能瓶颈
        优化绝对是建立在对已有程序执行效率的分析结果上。在我的程序中经历的优化有:在单线程性能已无法提高时,选择多线程 --> 解决线程争用共享资源 --> 排除很多无效数据也要下载文件且占据网络资源的情况 --> 解决部分数据依赖于第三方jar包,长时间没有数据返回的问题等。优化之前在可能出现性能问题的地方设置时间点,分析执行时间,以执行时间为依据做代码review。

3. 让程序更聪明些
        在程序运行期,我们希望得到它的执行进度、效率、指出程序瓶颈在哪,更期望程序从主动从问题中恢复,这些要求在程序开发阶段不会考虑太全,需要经过实践的验证,并不断补充。这个问题以前就认识到,但要写出些能上得了台面的东西,还是需要不断积累。
  • 在网络超时,系统负载高的时候能减缓执行,反之加快执行速度。
  • 如果某些资源在使用一段时间后频繁出现访问延时,就每隔一段时间重启执行程序。
  • 分析每个线程的执行效率,或分析线程数量的较优解
  • ... ...

4. 对BufferedWriter的并发访问
        程序中多线程往同一文件中写数据,使用BufferedWriter。之前没有看过BufferedWriter的代码,在访问BufferedWriter之前做同步处理,并在每次append()之后都做flush()操作,造成程序性能损耗严重。在同事的提醒下,修正为每个线程执行N次后再做flush。
        看了下BufferedWriter的代码,对上面的两个问题的解释:
        1. 多线程访问BufferedWriter是否需要同步
        BufferedWriter自带锁,同步对流的访问,所以在外面的同步可要可不要。(append同write方法)

protected Object lock;
public void write(int c) throws IOException {
	synchronized (lock) {
	    ensureOpen();
	    if (nextChar >= nChars)
		flushBuffer();
	    cb[nextChar++] = (char) c;
	}
}


        2. 如果append后不做flush,谁来flush
        BufferedWriter自设缓存,且默认大小为8K,大小可修改。

private char cb[];
private static int defaultCharBufferSize = 8192;
	
public void write(int c) throws IOException {
      synchronized (lock) {
	    ensureOpen();
	    if (nextChar >= nChars)
		flushBuffer();
	    cb[nextChar++] = (char) c;
	}
}

        在往BufferedWriter写数据时,当它发现缓存已满,就将缓存数据写入流中,将新到的数据再次放入缓存中。也就是说如果程序不主动flush的话,当数据值积累到默认缓存大小时,BufferedWriter会自动将缓存数据flush入writer流中。
        还有,当BufferedWriter关闭的时候,也会把所有缓存数据自动flush.

public void close() throws IOException {
	synchronized (lock) {
	    if (out == null) {
		return;
	    }
	    try {
	        flushBuffer();
	    } finally {
	        out.close();
	        out = null;
	        cb = null;
	    }
     }
}
1
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics