第28篇 rabbitmq IntAllocator 源码分析

本文介绍了一个基于BitSet实现的int类型数值分配类IntAllocator,它通过BitSet特性实现数字的分配与回收,并提供了测试案例验证其正确性。

int类型数值分配类, 不是线程安全的

1、成员变量

变量名默认值描述
final int loRange
final int hiRange
final int numberOfBitshiRange-logRange (数字个数)
int lastIndex0搜索free的数字
final BitSet freeSet表示某个数字是否被分配了

2、方法

方法名称描述图示
IntAllocator(int bottom, int top)构造方法,这个范围都是包含的,创建freeSet对象,将每个位置都设置为0
int allocate()分配可一个可用数字
void free(int reservation)释放某个数字
boolean reserve(int reservation)预定某个数字

2.1、总结

  1. 本质也就是利用BitSet特性,通道数是固定的,用完就没了,有没有类似令牌味道,可以用来限流否?

3、Test示例代码

  • public class IntAllocatorTests {
    
        private static final int TEST_ITERATIONS = 50000;
        private static final int HI_RANGE = 100000;
        private static final int LO_RANGE = 100;
        private final IntAllocator iAll = new IntAllocator(LO_RANGE, HI_RANGE);
    
        private final Random rand = new Random(70608L);
    
        /**
         * 随机生成序号,保存这个值,如果重复了就删除
         * @throws Exception
         */
        @Test public void reserveAndFree() throws Exception {
            Set<Integer> set = new HashSet<Integer>();
            for (int i = 0; i < TEST_ITERATIONS; ++i) {
                // 随机生成一个数字
                int trial = getTrial(rand);
                if (set.contains(trial)) {
                    // 重复就是释放当前数字所在占位置
                    iAll.free(trial);
                    set.remove(trial);
                } else {
                    //将当前这个数字添加到IntAllocator,也就是BitSet中
                    assertTrue("Did not reserve free integer " + trial, iAll.reserve(trial));
                    set.add(trial);
                }
            }
    
            for (int trial : set) {
                // 已经占用不能重复插入新数字
                assertFalse("Integer " + trial + " not allocated!", iAll.reserve(trial));
            }
        }
    
        /**
         * 随机占用位置,不用指定
         * @throws Exception
         */
        @Test public void allocateAndFree() throws Exception {
            Set<Integer> set = new HashSet<Integer>();
            for (int i=0; i < TEST_ITERATIONS; ++i) {
                if (getBool(rand)) {
                    int trial = iAll.allocate();
                    assertFalse("Already allocated " + trial, set.contains(trial));
                    set.add(trial);
                } else {
                    if (!set.isEmpty()) {
                        int trial = extractOne(set);
                        assertFalse("Allocator agreed to reserve " + trial, iAll.reserve(trial));
                        iAll.free(trial);
                    }
                }
            }
    
            for (int trial : set) {
                assertFalse("Integer " + trial + " should be allocated!", iAll.reserve(trial));
            }
        }
    
        /**
         * toString方法测试,
         * @throws Exception
         */
        @Test public void testToString() throws Exception {
            IntAllocator ibs = new IntAllocator(LO_RANGE, HI_RANGE);
            assertEquals("IntAllocator{allocated = []}", ibs.toString());
            ibs.allocate();
            assertEquals("IntAllocator{allocated = [100]}", ibs.toString());
            for(int i = 200; i<211; i=i+4) {
                ibs.reserve(i);
                ibs.reserve(i+1);
                ibs.reserve(i+2);
            }
            assertEquals("IntAllocator{allocated = [100, 200..202, 204..206, 208..210]}"
                , ibs.toString());
        }
    
        private static int extractOne(Set<Integer> set) {
            Iterator<Integer> iter = set.iterator();
            int trial = iter.next();
            iter.remove();
            return trial;
        }
    		// 生成随机数字, 范围为LO_RANGE 到 HI_RANGE
        private static int getTrial(Random rand) {
            return rand.nextInt(HI_RANGE-LO_RANGE+1) + LO_RANGE;
        }
    		// 随机生成boolean值
        private static boolean getBool(Random rand) {
            return rand.nextBoolean();
        }
    }
    
    

3、总结

  1. 利用BitSet来确定某个数字是否已经使用过了
  2. 这个可以利用BitSet来限流或者说令牌
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值