如何制作这样的自定义并发列表?

时间:2017-12-27 12:10:39

标签: java concurrency

HI,我写了一个用于计算PV的函数,当来PV时,将PV写入redis。但我认为巨大的PV数量可能会导致redis流量问题。然后我使用ArrayList来缓存PV,当列表大小达到10时,将所有10 PV放到redis,然后清除List。

因为并发问题(List add,size,clear),我添加了同步到funciton,代码就是这样:

static ArrayList<Object> pvList = new ArrayList<Object>();
public synchronized void countPv(...){
    //........make a PV Object
    pvList.add(PV)
    if(pvList.size()>10){
        // add the 10 PV to redis
        addRedis(pvList.subList(0,10))
    }
    //delete
    pvList.subList(0,10).clear();
}
但是在压力测试中,它失去了一些PV,也许同步导致线程流量问题,如何改进这个解决方案?

  1. 把同步里面的功能可以提高一点。
  2. ConcurrnetLinkedQueue,Concurrent ...数组不适合这个问题,我想 THX

1 个答案:

答案 0 :(得分:0)

您的ArrayList pvList是该类的静态成员,但您的countPv方法是非静态的。

因此,如果调用synchronized方法调用了不同的实例变量,则countPv无效。想象一下,这个代码是在类PVObjectListFiller中定义的。所以你有一个带有这个代码的线程1:

PVObjectListFiller f1 = new PVObjectListFiller(...);
f1.countPv(...);

和另一个主题:

PVObjectListFiller f2 = new PVObjectListFiller(...);
f2.countPv(...);

在这种情况下,这些线程将不会同步,因为它们会针对不同的互斥锁(对象f1f2)进行同步。

要使方法同步,您有不同的可能性

countPv(...)方法设为静态:

public static synchronized void countPv(...) {
    // ...
}

其他可能性:使pvList成员非静态:

ArrayList<Object> pvList = new ArrayList<>();

第三种可能性:引入静态mutex对象进行同步:

static ArrayList<Object> pvList = new ArrayList<Object>();
private static Object pvMutex = new Object();
public void countPv(...) {
    // ............... make PV Object
    synchronized(pvMutex) {
        pvList.add(PV)
        if(pvList.size()>10){
            // add the 10 PV to redis
            addRedis(pvList.subList(0,10))
        }
        //delete
        pvList.subList(0,10).clear();
    }
}

这取决于您的要求应该首选哪种解决方案。