1

マルチスレッド環境で使用するhi-lo Idジェネレーターがあります。ジェネレーターは、スレッドごとに毎秒 10 万回まで呼び出すことができます

私は、うまく機能するかなり良い(そして安全な)実装を持っています。IdAllocator は、ID の次の「バッチ」をフェッチするオブジェクトです。これはスレッドセーフであると想定できます。また、batchSize をかなり高く設定しました (100 万)

private final IdAllocator idAllocator;
private final String idKey;
private final int batchSize;

private final Object lock = new Object();

private long currentId = 0;
private long nextFetchId = -1;

IdGeneratorImpl( IdAllocator idAllocator, String idKey, int batchSize )
{
    this.idAllocator = idAllocator;
    this.idKey = idKey;
    this.batchSize = batchSize;
}

public long getNextId()
{
    synchronized ( lock )
    {
        if ( currentId < nextFetchId )
        {
            long localCurrent = currentId;
            currentId++;
            return localCurrent;
        }

        currentId = idAllocator.allocateBatch( idKey, batchSize );
        nextFetchId = currentId + batchSize;

        return getNextId();
    }
}

現時点では、常にではありませんが、ほとんどの場合、これを競合のない方法で使用しています。ただし、将来的には複数のスレッドから呼び出されるようになります。

スレッドごとにこれの 1 つのインスタンスをインスタンス化することを検討しましたが、これがおそらく最良の方法です。ただし、知的/学習経験として、特に複数のスレッドが頻繁に呼び出しているときに getNextId() の潜在的な競合を減らすために、この実装を改善できるのではないかと思いましたか?

4

2 に答える 2

0

Hibernateを見ると、生成メソッドでTableHiLoGenerator単純なものが使用synchronizedされています。つまり、複数のスレッドが待機するため、一度に1つのスレッドだけがメソッドを実行します。あなたはあなたと同じことをしましたlock(これは少し冗長です-synchronizedメソッドは同じことをします)。したがって、実装は問題ないと結論付けます。

于 2010-08-09T22:19:27.650 に答える
0

最適化しすぎているに違いありません。100 万のバッチ サイズは、100 万回の挿入ごとに DB にアクセスすることを意味します。代わりに 1000 を使用した場合、パフォーマンスの違いは見られず、無駄な ID ははるかに少なくなります。確かに、longそれは大した問題ではありません。

すべてのスレッドで上記のことを行うと、スレッドごとに最大 100 万の ID が無駄になることになります。と大したことはありませんlong、私は知っています。

また、起動コストが不必要に増加し、多くのスレッド ローカル ガベージが残る可能性があります。繰り返しますが、大したことではありませんが、利点は何ですか? 上記のような短いコードには数ナノ秒かかりますが、DB アクセスにはそれよりも桁違いに時間がかかります。したがって、競合が実際に速度を低下させることはありません。

ただし、これを最適化する適切な方法は、おそらくAtomicLong. 同期よりもはるかに低いオーバーヘッドです。getAndIncrementオーバーランしたときは、同期ブロックを使用してのみ入力してくださいnextFetchId。このブロックでは、最初に別のスレッドが実行しようとしている作業を実行したかどうかを再確認し、そうでない場合はデータベースから次の ID を取得します。

はるかに簡単な方法は、休止状態HiLoOptimizerまたはそのより良いバリアントを使用することです。

于 2016-09-28T16:37:22.900 に答える