现在有个系统要同时处理很多个请求,对于每笔请求系统都会创建一个线程或从线程池中取出一条线程来处理,处理后计算出处理的时间,最后计算出总的时间现在的办法是用一个全局变量,在每条线程中将该线程计算出的处理时间累加到全局变量上,因为是多线程所以这个过程使用了锁但是这样的话,当线程数量庞大时,因为锁的缘故,多线程变单线程,这会严重影响系统性能,那么有什么办法不用锁或不用全局变量来实现所有处理时间的累加吗??

解决方案 »

  1.   

    有啊,用一个结构体,比如说是CocurrentHashMap,或者是简单的数组。
    把每一个线程的耗时,存到结构中,最后取出再相加即可。以数组为例,你创建一个线程的时候,告诉这个线程存储的位置即可,这样就不需要同步了。
    每一个线程操作自己的变量,就解决问题了,需要的时候再相加。
      

  2.   

    总是要锁的,我还想不出来有什么办法不锁。但是只锁一个
    synchronized(lock){
      totalTime+=threadTime;
    }
    应该不至于导致太大的开销。
      

  3.   

    对于2楼,不需要吗?如果两个线程同时对这个变量进行操作呢??是否当一个线程对全局变量进行累加时这个变量已经被锁了,不允许其他线程访问??这方面不太清楚,请指教!对于1楼的方法我也想过,问题是如果不用锁的话我怎么知道存储的位置呢??如果说在线程中计算当前数组的大小,然后在下一个位置存入耗时,那么有这种可能:a线程计算出了当前数组长度为10,于是它打算在11的位置上写入但还未写入,但此时b线程也开始计算当前数组长度,由于a还未写入,所以长度还是为10,b也打算在11的位置上写入,那这样岂不是覆盖了
      

  4.   

    不要以该数组某位置是不是被set了为标志,而是以一个线程被创建为标志,
    创建了第一个线程,就以a[0]为单元,到时候写a[0]创建了第二个线程的时候,就把a[1] 分配给它。
    明白我的意思不?
      

  5.   

    这里高手多,过来学习一下,顺便说说自己的想法,仅供参考。我对这个问题的理解是:楼主认为
    synchronized(lock){ 
      totalTime+=threadTime; 

    导致太大的开销,因为有锁。那么CocurrentHashMap也是不行的,因为也用到了锁。对简单数组进行同步也是不行的,因为也用到了锁。一楼的高手认为:以数组为例,你创建一个线程的时候,告诉这个线程存储的位置即可,这样就不需要同步了。 每一个线程操作自己的变量,就解决问题了,需要的时候再相加。这个方案我考虑了很久,开始感觉是可以的。不用同步数组,这样就不用锁了。但是仔细一想,那个线程在数组中的存储位置还是需要同步,正如楼主自己分析的那样。基于以上讨论:感到只有用java.util.concurrent.atomic.AtomicInteger或者java.util.concurrent.atomic.AtomicLong了。那是一种 lock-free 或 wait-free 方法。下面这篇文章对它和同步的速度进行了比较:
    http://www.ibm.com/developerworks/java/library/j-jtp11234/以上是我非常粗略的分析,希望大家多提意见,共同学习进步。
      

  6.   


    又仔细看了看,用线程池的话这样是可以的。汗...不过楼主正好可以比较一下这个方案和java.util.concurrent.atomic.AtomicLong哪个快。单从编码角度来讲,java.util.concurrent.atomic.AtomicLong会比较简单一些。
      

  7.   

    呵呵  阿牛提供的AtomicLong果然方便,不过我在计算总时间的同时,还要一个一个比较得出最大响应时间和最小响应时间,这样的话就只能用甘草的方法使用数组先将时间保存下来,然后再比较和累加但是这样的话开始要配置与线程池最大容量相等大小的数组,若这个容量很大的话那不是会造成比较大的空间消耗?如我上面所说的,可不可以在每个线程动态的创建自己的存储空间呢?这个在多线程中可行吗??
      

  8.   

    如果是C的话,可以直接操作地址,好像就方便了。
    在Java里,不知道多线程同时访问数组中的两个元素会不会抛异常???
    至于你说的数组大小的问题,我觉得那是小问题,就算定义一个1000个元素的数组,占用的内存也大不到哪去。
      

  9.   

    AtomicLong, MARK,对实现XRuby有帮助。,
      

  10.   

    恩对,所以我是这样处理的:
    数组的大小不是线程池大小,而是和请求的数量相同,每个请求有一个唯一的流水号,流水号的获得就是使用AtomicLong累加获得的,每个请求的时间存入与流水号对应的数组中的位置,全部处理完了之后再来处理数组中的时间,这样不敢说是最好的方法,但至少解决问题了  呵呵