显示标签为“多线程”的博文。显示所有博文
显示标签为“多线程”的博文。显示所有博文

2008年8月30日星期六

血的教训告诉我们:最好不要多线程共享一个数据库连接

今天遇到一个奇怪的问题,有一段程序,会被多个线程并行访问,因为没有涉及到数据库写操作,所以就偷懒共享了一个DAO,但是发现一旦并发线程超过2个,就会出现异常,而且还是很奇怪的异常,好像是说数据库没有响应。调试了半天没发现什么问题,后来把DAO对象设置成了ThreadLocal,问题消失了……看来用一个数据库连接最好不要被多个线程同时操作。
最近经常在多线程同步上出问题,上午的时候出现了一个锁死的问题:有一个调用在一个同步块里面锁死了(因为另一个线程异常退出了,没有给这个线程解锁)然后后面紧跟着所有线程都停在了同步块上。在Profiler里一片红红的,好不壮观。
话说今天这个锁死的解决多亏了jconsoler和jvisualvm,这两个工具是最新的几个JDK版本才提供的,他们提供了对Java应用程序的本地或远程的即使监视和分析的功能。jconsole可以把每个线程的运行状态和阻塞原因打印出来,配合jvisualvm的可视化线程图表就可以确定到底是那个(些)线程进行了锁死,并有针对性的进行修复。
再废话一句:这两个工具好像都是基于JMX的,所以说JMX真是个好物啊~~

2008年7月22日星期二

多线程环境下的性能杀手:日志记录

今天晚上做了一个性能测试,发现在同等条件下,使用日志的处理速度比关闭所有日志慢了接近10被。
我的应用是一个基于Mian的多线程服务器程序,在打开日志时进行压力测试,发现Profiler的Thread图表基本上是万里河山一片红:
根据图例,红色代表线程正在等待某个监视器。但是我的事务代码基本上没有什么使用同步的东西啊……数据库连接也用ThreadLocal了,不应该出现这种情况啊。
经过检查,发现拖慢处理速度的就是平时经常使用的日志。因为Logger的方法都是同步的(或者从根本上说,System.out和System.err就是一个同步的输出流)所以造成线程在处理时不得不停下来等待其他线程完成日志输出。就算不用Logger,用System.out.println()也是一样的道理。
编辑日志属性,关闭所有日志以后,性能有了极大的提高,每秒能处理的请求数量提升了13倍左右。