ID回收在利用
1 使用场景
假设有这样的需求,我的电脑最多允许他开8个窗口,每个窗口需要分配一个唯一id,id只能从0-8里面取,当我的窗口被关闭后,分配的id就没用了,id就需要回收,id给下个窗口用,这就可以用这个代码,需求挺简单,各自有各自写法
代码编写的思路:
1 创建byte数组,用数组角标代表id,用数组内容代表id使用状态
2 假设有1000个id,我不直接创建长度为1000的数组,而是把这1000分成若干份数组,第一份数组id被分配完毕后,才去创建下一份数组,以此伦推
代码如下
/**
* Created by lgs
*
* Id分配,Id被回收后可以再次使用
*/
public class DistributionId {
//id已被使用的状态
public static final byte STATUS_USED = 1;
//id状态没有被使用
public static final byte STATUS_NOT_USED = 0;
//id分配的容器
private byte[][] ids;
//最多等级
private int maxLevel;
//每个等级分配的数量
private int levelLength;
//标准id,第一个id,以后所有id在此基础上进行累加
private int standardId;
public DistributionId() {
//默认最多分配512个id
this(8, 64);
}
//设置标准Id,以后所有id在此基础上累加,该方法在id没有被使用之前生效
public synchronized boolean setStandardId(int standardId) {
if (this.standardId == standardId)
return true;
byte[][] ids = this.ids;
for (int i = 0; i < ids.length; i++) {
byte[] levelArrId = ids[i];
if (levelArrId == null)
continue;
for (int j = 0; j < levelArrId.length; j++) {
//已使用就不可以被设置
if (levelArrId[j] == STATUS_USED)
return false;
}
}
this.standardId = standardId;
return true;
}
//释放所有id
public synchronized void releaseAll() {
ids = new byte[maxLevel][];
}
/**
* 总共可使用的id等于maxLevel*levelLength
*/
public DistributionId(int maxLevel, int levelLength) {
this.maxLevel = maxLevel;
this.levelLength = levelLength;
ids = new byte[maxLevel][];
}
/**
* 获取一个没有被占用的id,id从0开始计数,当所有id都占满没有被回收,返回-1
*/
public synchronized int getId() {
int policyDecisionLevel = getPolicyDecisionLevel();
if (policyDecisionLevel == -1) return -1;
byte[] levelArr = ids[policyDecisionLevel];
if (levelArr == null)
levelArr = initLevelId(policyDecisionLevel);
if (levelArr == null)
return -1;
for (int i = 0; i < levelArr.length; i++) {
int id = levelArr[i];
//使用就不可以在使用
if (id == STATUS_USED)
continue;
levelArr[i] = STATUS_USED;
//id按等级累加
return standardId + (policyDecisionLevel * levelLength) + i;
}
return -1;
}
/**
* 释放Id,以便后续再次使用
*/
public boolean releaseId(int id) {
return changeStatus(STATUS_NOT_USED, id);
}
//改变值的状态
protected synchronized boolean changeStatus(byte status, int id) {
id = id - standardId;
int levele = id / levelLength;
int index = id % levelLength;
if (levele >= ids.length) return false;
byte[] levelArr = ids[levele];
if (levelArr == null)
levelArr = initLevelId(levele);
if (levelArr == null || index >= levelArr.length) return false;
levelArr[index] = status;
return true;
}
/**
* 占有此id,不允许其他使用,只有调用releaseId()才可以再次使用
*/
public boolean occupyId(int id) {
return changeStatus(STATUS_USED, id);
}
//获取可用缓存的等级
protected int getPolicyDecisionLevel() {
for (int i = 0; i < ids.length; i++) {
byte[] levelArr = ids[i];
if (levelArr == null || levelEnable(levelArr))
return i;
}
return -1;
}
//以三个点来决策此等级是否可用
protected boolean levelEnable(byte[] levelArr) {
return levelArr[0] == STATUS_NOT_USED ? true : levelArr[levelArr.length / 2] ==
STATUS_NOT_USED ? true : levelArr[levelArr.length - 1] == STATUS_NOT_USED ?
true : false;
}
//初始化等级
protected synchronized byte[] initLevelId(int level) {
byte[] levelArr = ids[level];
if (levelArr == null)
levelArr = ids[level] = new byte[levelLength];
return levelArr;
}
}
public class TestId{
public static void main(String [] args){
DistributionId distributionId = new DistributionId();
//设置id分配的基准,以10为标准
distributionId.setStandardId(10);
int id = distributionId.getId();
System.out.println("id="+id);//打印结果为10
id = distributionId.getId();
System.out.println("id="+id);//打印结果为11
distributionId.releaseId(10);//释放10的id
id = distributionId.getId();
System.out.println("id="+id);//打印结果为10
id = distributionId.getId();
System.out.println("id="+id);//打印结果为12
distributionId.releaseAll();//释放所有id
//设置id分配的基准,以0为标准
distributionId.setStandardId(-2);
id = distributionId.getId();
System.out.println("id="+id);//打印结果为-2
//把5*20个id分成5份,此时只会创建长度为20的数组,等到id不够用才会扩展
distributionId = new DistributionId(5,20);
distributionId.setStandardId(0);//设置标准为0,默认就是0
distributionId.occupyId(1);//占用为1的id,那么1不能被用了
System.out.println(distributionId.getId());//打印结果为0
System.out.println(distributionId.getId());//打印结果为2,id1被占
System.out.println(distributionId.getId());//打印结果为3
distributionId.releaseId(1);//释放为1的id,1又可以用了
System.out.println(distributionId.getId());//打印结果为1
System.out.println(distributionId.getId());//打印结果为4
distributionId.releaseAll();//释放所有id
System.out.println(distributionId.getId());//打印结果为0
}
}