0

2つの列があるデータベースに挿入する必要があります-

ID Primary Key String
Data String

つまり、IDは毎回一意である必要があります。そうでない場合、duplicate row in unique index挿入中に例外がスローされます。そして、私はこの範囲の間でIDを選択する必要があります1-100000

つまり、各スレッドは常に一意の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);
        }

    }
}   
4

2 に答える 2

2

使用済みIDをキューに戻すことを意味します。pool.offer(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を検索する必要があります。少し高めのタイプもご利用いただけます。identityauto-incrementguid

プログラムを再起動するときは、最後に割り当てられたIDの後で開始する必要があることに注意してください。ただし、キューは必要ありません。最後に割り当てられたIDに初期化されたプライベート変数をインクリメントして返すsyncedメソッドをIdProvider持つクラスだけです。nextId

于 2013-02-06T01:46:49.660 に答える