0

我需要插入有两列的数据库 -

ID Primary Key String
Data String

所以这意味着ID每次都应该是唯一的,否则duplicate row in unique index插入时会抛出异常。我需要在这个范围内选择 ID1-100000

所以这意味着每个线程应该始终使用唯一的 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);
        }

    }
}   
4

2 回答 2

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。

于 2013-02-06T01:33:42.463 回答
1

identity列是数据库在每次插入时为其分配一个新的唯一值的列。看这里

我不知道这个XpressMP数据库,但你应该在文档中搜索identityorauto-increment类型。您也可以guid以稍高的成本使用一种类型。

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

于 2013-02-06T01:46:49.660 回答