das*_*ght 28
创建一个静态实例变量,并Interlocked.Increment(ref nextId)
在其上使用.
class Robot {
static int nextId;
public int RobotId {get; private set;}
Robot() {
RobotId = Interlocked.Increment(ref nextId);
}
}
Run Code Online (Sandbox Code Playgroud)
注意#1:using nextId++
仅在非并发环境中有效; Interlocked.Increment
即使您从多个线程分配机器人也能正常工作.
编辑这不涉及重复使用机器人ID.如果需要重用,解决方案要复杂得多:您需要一个可重用ID列表,以及ReaderWriterLockSlim
访问该列表的代码周围.
class Robot : IDisposable {
static private int nextId;
static private ReaderWriterLockSlim rwLock = new ReaderWriterLockSlim();
static private IList<int> reuseIds = new List<int>();
public int RobotId {get; private set;}
Robot() {
rwLock.EnterReadLock();
try {
if (reuseIds.Count == 0) {
RobotId = Interlocked.Increment(ref nextId);
return;
}
} finally {
rwLock.ExitReadLock();
}
rwLock.EnterWriteLock();
try {
// Check the count again, because we've released and re-obtained the lock
if (reuseIds.Count != 0) {
RobotId = reuseIds[0];
reuseIds.RemoveAt(0);
return;
}
RobotId = Interlocked.Increment(ref nextId);
} finally {
rwLock.ExitWriteLock();
}
}
void Dispose() {
rwLock.EnterWriteLock();
reuseIds.Add(RobotId);
rwLock.ExitWriteLock();
}
}
Run Code Online (Sandbox Code Playgroud)
注2:如果你想提前重用较小的ID较大的ID(而不是重用晚些时候公布的ID之前早些时候发布的ID,我编码它),你可以替换IList<int>
使用SortedSet<int>
,使零件周围一些调整,其中一个ID被重用是从集合中获取的.
A.R*_*.R. 11
这将解决问题,并以一种良好的线程安全方式运行.当然,由你自己处理机器人等等.显然,对于大量的机器人来说它不会有效,但有很多方法可以解决这个问题.
public class Robot : IDisposable
{
private static List<bool> UsedCounter = new List<bool>();
private static object Lock = new object();
public int ID { get; private set; }
public Robot()
{
lock (Lock)
{
int nextIndex = GetAvailableIndex();
if (nextIndex == -1)
{
nextIndex = UsedCounter.Count;
UsedCounter.Add(true);
}
ID = nextIndex;
}
}
public void Dispose()
{
lock (Lock)
{
UsedCounter[ID] = false;
}
}
private int GetAvailableIndex()
{
for (int i = 0; i < UsedCounter.Count; i++)
{
if (UsedCounter[i] == false)
{
return i;
}
}
// Nothing available.
return -1;
}
Run Code Online (Sandbox Code Playgroud)
还有一些测试代码可以很好地衡量.
[Test]
public void CanUseRobots()
{
Robot robot1 = new Robot();
Robot robot2 = new Robot();
Robot robot3 = new Robot();
Assert.AreEqual(0, robot1.ID);
Assert.AreEqual(1, robot2.ID);
Assert.AreEqual(2, robot3.ID);
int expected = robot2.ID;
robot2.Dispose();
Robot robot4 = new Robot();
Assert.AreEqual(expected, robot4.ID);
}
Run Code Online (Sandbox Code Playgroud)