java - 插入时应为每个线程分配唯一的 id

标签 java multithreading blockingqueue

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

ID Primary Key String
Data String

这意味着ID每次都应该是唯一的,否则在插入时会抛出唯一索引中的重复行异常。我需要在这个范围 1-100000

之间选择 ID

这意味着每个线程应该始终使用唯一的 id-

下面是我编写的多线程程序,每次从ArrayBlockingQueue获取后都会将不同的唯一ID插入数据库。

那么这个程序是否是线程安全的?或者有没有其他更好的方法来获取每个线程每次的唯一ID?或者下面的程序可能会导致唯一索引中出现重复行

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);
        }

    }
}   

最佳答案

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。

关于java - 插入时应为每个线程分配唯一的 id,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14720092/

相关文章:

multithreading - TPL 中的最大任务数?

mysql - Mysql INSERT 操作如何针对可能的重复条目进行优化?

java - 阻塞队列将等待元素出队多长时间?

java - 未使用提供的队列实例在 SEDA 端点上使用的消息

java - 谷歌云翻译和Java编码错误

java - 断言处理在 "console"和 "result of running suite"中给出不同的结果

java - Gradle:程序类型已经存在

java - Java 中的 Thread.sleep() 有多昂贵?

java - 仅当字段是时间戳时如何按日期选择?

Java异步方法调用/后台处理