2013-02-06 40 views
0

被分配唯一的ID,我需要插入其中有两个columns-每个线程应该同时插入

ID Primary Key String 
Data String 

数据库因此,这意味着ID应该是唯一的每一次,否则会抛出一个异常duplicate row in unique index插入时。我需要在这个范围内1-100000

之间做出选择ID因此,这意味着每个线程应该使用唯一的ID始终在线

下面是多线程程序我写了,将后每次插入到数据库不同的独特的ID从ArrayBlockingQueue获得。

所以这个程序将是线程安全或不是?或者还有没有其他更好的方法来获得每个线程每次唯一的ID?或者下面的程序可能会导致duplicate row in unique index

private static LinkedList<Integer> availableExistingIds = new LinkedList<Integer>(); 

public static void main(String[] args) { 

     for (int i = 1; i <= 100000; i++) { 
      availableExistingIds.add(i); 
     } 

     BlockingQueue<Integer> pool = new ArrayBlockingQueue<Integer>(200000, false, availableExistingIds); 

     ExecutorService service = Executors.newFixedThreadPool(10); 

      for (int i = 0; i < noOfTasks * noOfThreads; i++) { 
       service.submit(new ThreadTask(pool)); 
      } 
} 

class ThreadTask implements Runnable { 

    private BlockingQueue<Integer> pool; 
    private int id; 

    public ThreadTask(BlockingQueue<Integer> pool) { 
     this.pool = pool; 
    } 

    @Override 
    public void run() { 

     try { 
      dbConnection = getDBConnection(); 
      preparedStatement = dbConnection.prepareStatement(INSERT_SQL); 

      id = pool.take(); 

      preparedStatement.setString(1, String.valueOf(id)); 
      preparedStatement.setString(2, ACCOUNT); 

      preparedStatement.executeUpdate(); 

     } finally { 
     pool.offer(id); 
     } 

    } 
} 
+0

哪个数据库?你不能使用“身份”类型吗? –

+0

我正在使用一个名为XpressMP的新数据库。你能否以身份解释我是什么意思? – AKIWEB

回答

2

pool.offer(id)意味着你把用过的ID回到队列 - 因此它可以被另一个线程后来被重用。这可能会成为一个问题(因为队列是FIFO,您将在第100,001个插入时获得重复的ID)。

在任何情况下,似乎很复杂,当一个静态AtomicInteger会做同样的事情,而不必使用队列:

class ThreadTask implements Runnable { 

    private final AtomicInteger id; 

    ThreadTask(AtomicInteger id) { 
     this.id = id; //in your main thread: id = new AtomicInteger(minId); 
    } 

    @Override 
    public void run() { 
     dbConnection = getDBConnection(); 
     preparedStatement = dbConnection.prepareStatement(INSERT_SQL); 

     preparedStatement.setString(1, String.valueOf(id.getAndIncrement())); 
     preparedStatement.setString(2, ACCOUNT); 

     preparedStatement.executeUpdate(); 
    } 
} 

注:如评论,你的数据库大概可以分配唯一的ID为您服务。

+0

感谢assylias的建议。所以在你上面提到的例子中。每次从1开始,它都会增加id的权利?如果我需要从特定范围获得唯一身份证,那么呢? – AKIWEB

+0

@ Nevzz03您可以将初始化更改为'id = new AtomicInteger(lowerBoundOfYourRange);'或者有一个构造函数接受AtomicInteger并管理主代码中的id范围。 – assylias

+0

我已经更新了一个示例,其中id传递给了构造函数 - 确保所有任务都使用相同的方法。 – assylias

1

identity列是数据库为每个插入指定一个新的唯一值的列。见here

我不知道这XpressMP数据库,但你应该寻找文档的identityauto-increment类型。您也可以使用​​类型,成本稍高。

请记住,当程序重新启动时,您必须在上次分配的ID之后开始。但你仍然不需要队列,只需要一个带有同步nextId方法的IdProvider类,该方法递增并返回已初始化为最后分配的ID的私有变量。

相关问题