ID回收在利用

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
    }

}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值