现在我要实现一个功能,做一个在线用户数统计功能,这是一个多线程的环境,同时访问的用户数非常大,我把在线用户数放在一个 int 里。它的工作流程大致如下:用户请求过来,我 int 加 1,等用户请求处理完,我 int 减 1。
private int online = 0;public synchronized void plus() {
    online++;
}
public synchronized void minus() {
    online--;
}
现在有一个问题,如果我用 synchronized 来同步,感觉性能上会有影响,如果不用synchronized ,用来统计的 int 数据又不准确。所以想问下各位,有没有更好的解决方案。

解决方案 »

  1.   


    我这个在线访问不是用于网站的 session ,我做的是一个接口系统,一个用户一次访问可能只有几百毫秒就结束了。至于访问量,后面也会做,所以对这个 int 做实时操作非常频繁。
      

  2.   

    可以如下改动,对性能会有所提高private int online = 0;
    //使用同步块而不使用同步方法,使得占用锁的时间较少来提升性能。
    public void plus() {
    synchronized(this) {
    online++;
    }
    }
    public void minus() {
        synchronized(this) {
    online--;
    }
    }private AtomicInteger online = new AtomicInteger(0);
    //因为AtomicInteger是原子操作,所以不用同步。这种方式要比上一种更加能提升性能。
    public void plus() {
    online.getAndIncrement();
    }
    public void minus() {
        online.getAndDecrement();
    }
      

  3.   

    哦,所以你这个其实并不是Session意义上的在线。而是:当前并发数。
    这种问题一般用分割计数器的方式来处理,也即:初始化:
    private static final int CONCURREN_RATE = 100;
    Counter[] cs = new Counter[CONCURREN_RATE];
    // 初始化略使用时:
    Counter c = cs[hash(用户对象) % CONCURREN_RATE];
    c.plus();统计一般是定期统计,把所有Counter做个求和就行了,对于统计来说,一般其实也不需要精准;也就是可以脏读,不要去synchronized了。不过你这个还不是最困难的,呵呵,困难的是集群环境下,还要做合并。
      

  4.   


    Counter就是你自己封装的计数器了,直接用AtomicInteger也行,看场合。AtomicInteger的缺点是超高并发下性能表现会搓,大部分情况下会比synchronized更好。