最近在做一个分布式批处理项目,业务逻辑复杂,数据量200万左右,处理过程大概如下:
1.查询满足条件的单子,并将计算、判断需要的基础数据查出来(批量查出来,当然查询过程中有做数据的分布式,不然一次性查出来不现实,这里不做赘述);
2.根据查询的数据计算出结果;
3.对需要提交的数据进行加锁操作
4.重新查询基础数据,与之前查询的数据进行对比,检查数据是否有改变,如果数据有变化,则将数据丢掉,本次计算不生效(可能大家有疑问,为什么不一开始就进行锁表操作呢?因为还有频繁的实时业务对于数据进行操作,所以要尽量是锁表的时间缩短)
5.批量提交
对于第四个点有两个地方比较耗时,1.现在已知单号,要根据单号查询数据,不能够根据单号一条一条查询,这样每次都与数据库有交互,很慢,那需要批量查询出来,可能有人想到用in,但是有一个问题in的参数有限制,对于oracle是1000,那怎么办?请参考文章https://blog.csdn.net/tiantiandjava/article/details/80205821(经过实测发现文章里提到的函数的参数有4000字符的限制,由于我们的参数比较长,故采用了in()or in().....形式,在java端进行拼写sql)
2.数据已经批量查出来,是两个集合,如何比较呢?参考https://blog.csdn.net/has330338724/article/details/50532901(注意集合里是对象的话,如果想用equal方法,需要重写hashcode方法和equal方法)
对于第5点,参考https://blog.csdn.net/codejas/article/details/79536863
https://blog.csdn.net/qq_15003505/article/details/80428249
关于hashcode()和equal()
hashCode()方法和equal()方法的作用其实一样,在Java里都是用来对比两个对象是否相等一致,那么equal()既然已经能实现对比的功能了,为什么还要hashCode()呢?
因为重写的equal()里一般比较的比较全面比较复杂,这样效率就比较低,而利用hashCode()进行对比,则只要生成一个hash值进行比较就可以了,效率很高,那么hashCode()既然效率这么高为什么还要equal()呢?
因为hashCode()并不是完全可靠,有时候不同的对象他们生成的hashcode也会一样(生成hash值得公式可能存在的问题),所以hashCode()只能说是大部分时候可靠,并不是绝对可靠,所以我们可以得出:
1.equal()相等的两个对象他们的hashCode()肯定相等,也就是用equal()对比是绝对可靠的。
2.hashCode()相等的两个对象他们的equal()不一定相等,也就是hashCode()不是绝对可靠的。
所有对于需要大量并且快速的对比的话如果都用equal()去做显然效率太低,所以解决方式是,每当需要对比的时候,首先用hashCode()去对比,如果hashCode()不一样,则表示这两个对象肯定不相等(也就是不必再用equal()去再对比了),如果hashCode()相同,此时再对比他们的equal(),如果equal()也相同,则表示这两个对象是真的相同了,这样既能大大提高了效率也保证了对比的绝对正确性!
这种大量的并且快速的对象对比一般使用的hash容器中,比如hashset,hashmap,hashtable等等,比如hashset里要求对象不能重复,则他内部必然要对添加进去的每个对象进行对比,而他的对比规则就是像上面说的那样,先hashCode(),如果hashCode()相同,再用equal()验证,如果hashCode()都不同,则肯定不同,这样对比的效率就很高了。
然而hashCode()和equal()一样都是基本类Object里的方法,而和equal()一样,Object里hashCode()里面只是返回当前对象的地址,如果是这样的话,那么我们相同的一个类,new两个对象,由于他们在内存里的地址不同,则他们的hashCode()不同,所以这显然不是我们想要的,所以我们必须重写我们类的hashCode()方法,即一个类,在hashCode()里面返回唯一的一个hash值,比如下面:
自定义一个类
class Person{
int num;
String name;
public int hashCode(){
return num*name.hashCode();
}
}
由于标识这个类的是他的内部的变量num和name,所以我们就根据他们返回一个hash值,作为这个类的唯一hash值。
所以如果我们的对象要想放进hashSet,并且发挥hashSet的特性(即不包含一样的对象),则我们就要重写我们类的hashCode()和
equal()方法了。像String,Integer等这种类内部都已经重写了这两个方法。
当然如果我们只是平时想对比两个对象 是否一致,则只重写一个equal(),然后利用equal()去对比也行的。
哈希码(HashCode)
哈希码产生的依据:哈希码并不是完全唯一的,它是一种算法,让同一个类的对象按照自己不同的特征尽量的有不同的哈希码,但不表示不同的对象哈希码完全不同。也有相同的情况,看程序员如何写哈希码的算法。