业务场景:现有个接口,非方法级负载均衡,而是在接口内部实在,实现方法均摊。具体代码如下。
这里使用平均数来生成判断走那个逻辑,可能会出现均衡度不一样情况,比如高并发调用一千次,可能第一个走600,第二第三各走200。这样就无法实现比较均衡的平均分配。
100线程循环1000次,想当于调用10w次
具体代码:
/**
* @program: 工具箱
* @description
* 使用同步锁和洗牌算法 展示了如何在处理四个数字(a、b、c、d)的情况下实现均衡的累加。
* <p>
* 在 `saveOne()` 方法中,通过循环执行 `numRequests` 次请求。在每次循环中,我们首先使用 `getRandomIndex()` 方法获取一个随机索引,该方法会对索引进行随机打乱以实现均衡分布。
* <p>
* 然后,使用 `switch` 语句根据随机索引对 `a`、`b`、`c` 和 `d` 进行累加操作。
* <p>
* 接下来,我们输出当前的执行次数 `total`,以及每个数字的计数值 `a`、`b`、`c` 和 `d`。
* <p>
* 在 `getRandomIndex()` 方法中,我们将索引数组 `{0, 1, 2, 3}` 传递给 `shuffleArray()` 方法进行随机打乱,并返回打乱后的数组中的第一个索引。
* <p>
* `shuffleArray()` 方法使用 Fisher-Yates 洗牌算法来打乱数组元素的顺序,确保每个索引以均衡的方式出现。
* <p>
* 在 `main()` 方法中,我们创建 `TestController` 实例,并启动 30 个线程,每个线程执行 `saveOne(100)` 方法来模拟并发执行。
* <p>
* 通过以上代码,您可以观察到每个数字(a、b、c、d)的计数值在不同线程间进行均衡的累加,并输出执行次数和各数字的计数情况。这样可以实现较为均衡的处理。请注意,由于线程调度和竞争条件的存在,无法保证每个数字的计数完全相等,但整体上可以达到较好的均衡效果。
*/
private int total = 0;
private int a = 0;
private int b = 0;
private int c = 0;
private int d = 0;
public void saveOne(int numRequests) {
for (int i = 0; i < numRequests; i++) {
int randomIndex = getRandomIndex();
switch (randomIndex) {
case 0:
a++;
break;
case 1:
b++;
break;
case 2:
c++;
break;
case 3:
d++;
break;
}
total++;
System.out.println("执行了第->" + total);
System.out.println("a: " + a);
System.out.println("b: " + b);
System.out.println("c: " + c);
System.out.println("d: " + d);
}
}
/**
* Fisher–Yates shuffle 洗牌算法
* 这里的{0, 1, 2, 3}和上面case 0 1 2 4 一一对应.
*/
private int getRandomIndex() {
int[] indices = {0, 1, 2, 3};
shuffleArray(indices);
return indices[0];
}
/**
* Fisher–Yates shuffle 洗牌算法
* @param array
*/
private void shuffleArray(int[] array) {
Random random = new Random();
for (int i = array.length - 1; i > 0; i--) {
int index = random.nextInt(i + 1);
int temp = array[index];
array[index] = array[i];
array[i] = temp;
}
}
public static void main(String[] args) {
TestController example = new TestController();
for (int i = 0; i < 30; i++) {
Thread thread = new Thread(() -> example.saveOne(100));
thread.start();
}
}
private final Object lock = new Object(); // 添加同步锁
@ApiOperation(value = "负载均衡测试", notes = "负载均衡测试")
@GetMapping("/oneMQ1")
public void oneMQ1() {
int randomIndex = getRandomIndex();
synchronized (lock) {
total++;
switch (randomIndex) {
case 0:
a++;
break;
case 1:
b++;
break;
case 2:
c++;
break;
case 3:
d++;
break;
}
}
System.out.println("执行了第->" + total);
System.out.println("a: " + a);
System.out.println("b: " + b);
System.out.println("c: " + c);
System.out.println("d: " + d);
}
使用压测工具调用执行结果:
执行了第->100000
a: 25234
b: 25276
c: 24769
d: 24721
可以看出非常均匀的进行部分运算了
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/192735.html