很久以前写的一段代码,当时碰到这么一个需求,一个人想买二手车的人,对车有许多要求,比如要求车的颜色,车的排量,前驱还是后驱,车的已经使用年限等等,这个人填写了一系列的对要买的二手车的具体要求。然后数据库有很多待出售二手车,怎么把买车的顾客和二手车们做撮合匹配呢。由于匹配条件很多,每个匹配条件的权重也有不同,所以直接一条sql很难做到,并且用存储过程来做也有一定的问题,原因一方面计算条件复杂,而且计算完毕后返回的数据结构也比较复杂,当然可能和自己对存储过程的运用不够熟练也有关系。所以当时想了这个一个解决方案,每十分钟从数据库load一次有效的二手车信息到内存中,用户填完自己的需求表单后保存到数据库,不做及时匹配的原因在于用户一段时期内都有这个需求,不是一次性查询,然后用户使用匹配功能时,自动一对多的计算一次。ok,下面干货来了,每五分load一次没问题,但是如果用户匹配的时候系统真正做load呢,或者系统正在做匹配运算的时候,时候到了清空一下内存中的数据再load一次呢?恩,出问题了。
什么是,知道大众迈腾的人应该都熟悉。有DSG是迈腾的重要卖点之一。DSG变速器的工作过程中总是有2个档位是结合的,一个正在工作,另一个则为下一步做好 准备;
这里的代码就是模拟DSG的工作原理,每次系统中维护两份二手车数据,这两份数据是不同时间段的一份数据库数据copy。数据一在被销毁前的10分钟,数据二已经提前load了一份当前的最新数据等待被使用。
代码如下,欢迎拍砖,不拍不长进,但是杜绝人身攻击 :
public class ThreadLoadMatchableInvestCar extends Thread {
private static final int QUARTER_CYCLE = 5 * 1000 * 60;
private static int POSITION_1 = 1;
private static int POSITION_2 = 2;
private static int POSITION_3 = 3;
private static int POSITION_4 = 4;
private static int POSITION = 1;
private static ArrayList<MatchableInvestCarDTO> a = new ArrayList<MatchableInvestCarDTO>();
private static ArrayList<MatchableInvestCarDTO> b = new ArrayList<MatchableInvestCarDTO>();
private static ArrayList<MatchableInvestCarDTO> getA() {
return a;
}
private static ArrayList<MatchableInvestCarDTO> getB() {
return b;
}
private static void setA() {
InvestCar is = new InvestCar();
try {
a = is.loadMatchableInvestCarList();
} catch (Exception e) {
e.printStackTrace();
}
}
private static void setB() {
InvestCar is = new InvestCar();
try {
b = is.loadMatchableInvestCarList();
} catch (Exception e) {
e.printStackTrace();
}
}
public static ArrayList<MatchableInvestCarDTO> getInvestCarList() {
switch (POSITION) {
case 1:
return getA();//第一个四分之一周期应该取数据一
case 2:
return getA();//第二个四分之一周期应该取数据一
case 3:
return getB();//第三个四分之一周期应该取数据二
case 4:
return getB();//第四个四分之一周期应该取数据二
default:
return getA();
}
}
public void run() {
initializeInvestCarList();//第一次初始化数据一和数据二
while (true) {//不断循环更新数据
waitAMoment();//每5分钟为四分之一周期
resetPositon();//判断下一个是四分之一周期
resetInvestCarList();//判断此时是否该重新load一下数据和load那份数据
}
}
//休眠5分钟
private void waitAMoment() {
try {
sleep(QUARTER_CYCLE);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//第一次初始化两份数据
private void initializeInvestCarList() {
setA();
setB();
}
private void resetInvestCarList() {
switch (POSITION) {
case 2:
setB();//第二个四分之一周期提前吧数据二准备好了,等待第三个四分之一周期数据二的调用
break;
case 4:
setA();//第四个四分之一周期提前吧数据一准备好了,等待循环回来的第一个四分之一周期数据一的调用
break;
}
}
private void resetPositon() {
switch (POSITION) {
case 1:
POSITION = POSITION_2;
break;
case 2:
POSITION = POSITION_3;
break;
case 3:
POSITION = POSITION_4;
break;
case 4:
POSITION = POSITION_1;
break;
}
}
}