我在生成条形码的java代码中修复错误(线程问题)。根据设计,条形码只是一个数字而下一个"未使用"条形码是序列中的下一个。有990亿可能的数字。
首先,由于安全问题,我不喜欢自动递增的数字。我想生成随机数。
已使用的条形码存储在数据库表中。
如果条形码正在使用,很容易创建一个随机数并检查表格。但逻辑必须循环,直到找到一个未使用的随机数。到时候这可能是一项繁重的任务。
我认为具有1000个免费条形码的线程安全缓存可以完成这项工作,但构建或更新缓存可能非常繁重。
对设计执行查询的查询或可以返回一系列免费随机数的查询的任何建议?
我正在使用hibernate标准。
由于
答案 0 :(得分:4)
您可以使用Linear Feedback Shift Register。它们可以在一个循环中逐步执行具有特定位数的所有数字,而不会以看似随机的顺序重复。
这应该有效 - 这是我刚才写的一个严重缩减的版本。您将必须选择链接中描述的原始多项式。
您可以找到随机选择的原始多项式列表here。
/**
* Linear feedback shift register
*
* Taps can be found at:
* See http://www.xilinx.com/support/documentation/application_notes/xapp052.pdf
* See http://mathoverflow.net/questions/46961/how-are-taps-proven-to-work-for-lfsrs/46983#46983
* See http://www.newwaveinstruments.com/resources/articles/m_sequence_linear_feedback_shift_register_lfsr.htm
* See http://www.yikes.com/~ptolemy/lfsr_web/index.htm
* See http://seanerikoconnor.freeservers.com/Mathematics/AbstractAlgebra/PrimitivePolynomials/overview.html
*
* @author OldCurmudgeon
*/
public class LFSR implements Iterable<BigInteger> {
// Bit pattern for taps.
private final BigInteger taps;
// Where to start (and end).
private final BigInteger start;
// The poly must be primitive to span the full sequence.
public LFSR(BigInteger primitivePoly, BigInteger start) {
// Where to start from (and stop).
this.start = start.equals(BigInteger.ZERO) ? BigInteger.ONE : start;
// Knock off the 2^0 coefficient of the polynomial for the TAP.
this.taps = primitivePoly.shiftRight(1);
}
@Override
public Iterator<BigInteger> iterator() {
return new LFSRIterator(start);
}
private class LFSRIterator implements Iterator<BigInteger> {
// The last one we returned.
private BigInteger last = null;
// The next one to return.
private BigInteger next = null;
public LFSRIterator(BigInteger start) {
// Do not return the seed.
last = start;
}
@Override
public boolean hasNext() {
if (next == null) {
/*
* Uses the Galois form.
*
* Shift last right one.
*
* If the bit shifted out was a 1 - xor with the tap mask.
*/
boolean shiftedOutA1 = last.testBit(0);
// Shift right.
next = last.shiftRight(1);
if (shiftedOutA1) {
// Tap!
next = next.xor(taps);
}
// Never give them `start` again.
if (next.equals(start)) {
// Could set a finished flag here too.
next = null;
}
}
return next != null;
}
@Override
public BigInteger next() {
// Remember this one.
last = hasNext() ? next : null;
// Don't deliver it again.
next = null;
return last;
}
@Override
public void remove() {
throw new UnsupportedOperationException("Not supported.");
}
@Override
public String toString() {
return LFSR.this.toString()
+ "[" + (last != null ? last.toString(16) : "")
+ "-" + (next != null ? next.toString(16) : "") + "]";
}
}
@Override
public String toString() {
return "(" + taps.toString(32) + ")-" + start.toString(32);
}
}
public void test(int[] tap, int base) {
System.out.println("Test: " + Arrays.toString(tap));
// Build the BigInteger.
BigInteger primitive = BigInteger.ZERO;
for (int bit : tap) {
primitive = primitive.or(BigInteger.ONE.shiftLeft(bit));
}
// Stop at 100.
int count = 100;
LFSR lfsr = new LFSR(primitive, BigInteger.ONE);
for (BigInteger b : lfsr) {
if (count-- > 0) {
System.out.println(b.toString(base));
} else {
break;
}
}
}
public void test() {
// Just 6 bits.
int[] tap7 = {6, 5, 0};
test(tap7, 10);
// An example 48-bit tap.
int[] tap48 = {48, 46, 45, 44, 42, 40, 36, 34, 33, 32, 29, 27, 26, 20, 17, 16, 12, 11, 10, 5, 3, 1, 0};
test(tap48, 16);
}