生成随机条形码 – 一个设计问题

我正在修复生成条形码的java代码中的错误(线程问题)。 根据设计,条形码只是一个数字,下一个“未使用”条形码是序列中的下一个。 有990亿可能的数字。

首先,由于安全问题,我不喜欢自动递增的数字。 我想生成随机数。

已使用的条形码存储在数据库表中。

如果条形码正在使用,创建一个随机数并检查表是非常容易的。 但逻辑必须循环,直到找到一个未使用的随机数。 到时候这可能是一项繁重的任务。

我认为具有1000个免费条形码的线程安全缓存可以完成这项工作,但构建或更新缓存可能非常繁重。

对查询设计的任何建议或者可以返回一系列免费随机数的查询?

我正在使用hibernate标准。

谢谢

您可以使用线性反馈移位寄存器 。 它们可以在一个循环中逐步执行具有特定位数的所有数字,而不会以看似随机的顺序重复。

这应该有用 – 它是我刚才写的一个严重缩减的版本。 您将必须选择链接中描述的原始多项式。

您可以在此处找到随机选择的原始多项式列表。

/** * 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 { // 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 iterator() { return new LFSRIterator(start); } private class LFSRIterator implements Iterator { // 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); }