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,也许同步导致线程流量问题,如何改进这个解决方案?
答案 0 :(得分:0)
您的ArrayList pvList
是该类的静态成员,但您的countPv
方法是非静态的。
因此,如果调用synchronized
方法调用了不同的实例变量,则countPv
无效。想象一下,这个代码是在类PVObjectListFiller
中定义的。所以你有一个带有这个代码的线程1:
PVObjectListFiller f1 = new PVObjectListFiller(...);
f1.countPv(...);
和另一个主题:
PVObjectListFiller f2 = new PVObjectListFiller(...);
f2.countPv(...);
在这种情况下,这些线程将不会同步,因为它们会针对不同的互斥锁(对象f1
或f2
)进行同步。
要使方法同步,您有不同的可能性
将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();
}
}
这取决于您的要求应该首选哪种解决方案。