我有一个在多线程环境中使用的Hi-lo Id生成器。每个线程每秒最多可调用10万次生成器
我有一个相当不错(和安全)的实现,效果很好。 IdAllocator是获取ID的下一个“批次”的对象。您可以假定这是线程安全的。我还将batchSize设置得很高(一百万)
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();
}
}
目前,我主要(但不总是)以一种无竞争的方式使用它。但是,将来它将由多个线程调用。
我考虑过为每个线程实例化一个实例,这可能是最好的方法。但是,作为知识/学习经验,我想知道是否可以对这种实现进行改进,特别是当多个线程频繁调用getNextId()时,可以减少潜在的争用吗?
最佳答案
如果您查看Hibernate TableHiLoGenerator
,它将在生成方法中使用一个简单的synchronized
,这意味着多个线程将等待,因此只有一个线程一次执行该方法。您已经对lock
执行了相同的操作(这有点多余-synchronized
方法执行相同的操作)。因此,我认为您的实现很好。
关于java - 高低ID发生器的改进,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/3444459/