From f5ac4f8829f31be14b93f4e1835c67242a39d6b8 Mon Sep 17 00:00:00 2001 From: whaifree <49432110+whaibetter@users.noreply.github.com> Date: Mon, 19 Aug 2024 00:50:26 +0800 Subject: [PATCH] =?UTF-8?q?feat(interview):=20=E6=B7=BB=E5=8A=A0=E9=9D=A2?= =?UTF-8?q?=E8=AF=95=E9=A2=98=E5=92=8C=E8=A7=A3=E5=86=B3=E6=96=B9=E6=A1=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增ByteDance类,包含三道面试题的解决方案。 - 在meituan810类中添加了解决方案和相关代码。 - 重构并优化了RateLimitingRequestSplitter类的代码。 fix(threadpool): 修正CvmResetHandler中线程池参数顺序 重新排列CvmResetHandler中线程池执行器的参数,以确保正确分配任务并防止在任务完成前服务中断。 refactor(code): 移除无用的变量和代码段 在多个类中清理无用的变量和未使用的代码段,以提高代码的可读性和维护性。 --- .../whaifree/interview/qiuzhao/ByteDance.java | 224 ++++++++++++++++ .../interview/qiuzhao/meituan810.java | 252 ++++++++++++++++++ .../java/cn/whaifree/redo/redoAll/LCR001.java | 72 +++++ .../cn/whaifree/redo/redoAll/LeetCode416.java | 118 ++++++++ .../cn/whaifree/redo/redoAll/LeetCode5.java | 135 ++++++++++ .../cn/whaifree/redo/redoAll/LeetCode713.java | 58 ++++ .../test/RateLimitingRequestSplitter.java | 121 +++++++++ 7 files changed, 980 insertions(+) create mode 100644 src/main/java/cn/whaifree/interview/qiuzhao/ByteDance.java create mode 100644 src/main/java/cn/whaifree/interview/qiuzhao/meituan810.java create mode 100644 src/main/java/cn/whaifree/redo/redoAll/LCR001.java create mode 100644 src/main/java/cn/whaifree/redo/redoAll/LeetCode416.java create mode 100644 src/main/java/cn/whaifree/redo/redoAll/LeetCode5.java create mode 100644 src/main/java/cn/whaifree/redo/redoAll/LeetCode713.java create mode 100644 src/main/java/cn/whaifree/test/RateLimitingRequestSplitter.java diff --git a/src/main/java/cn/whaifree/interview/qiuzhao/ByteDance.java b/src/main/java/cn/whaifree/interview/qiuzhao/ByteDance.java new file mode 100644 index 0000000..36e0e22 --- /dev/null +++ b/src/main/java/cn/whaifree/interview/qiuzhao/ByteDance.java @@ -0,0 +1,224 @@ +package cn.whaifree.interview.qiuzhao; + +import java.util.HashMap; +import java.util.Scanner; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/8/18 18:55 + * @注释 + */ +public class ByteDance { + + + +} + +class ByteDancep1{ + /** + * 字数组 + * 4111 411 就是满足要求的 + * 字数组特殊数组个数 + * @param args + */ + public static void main(String[] args) { + Scanner in = new Scanner(System.in); + int i = in.nextInt(); + int[] nums = new int[i]; + for (int j = 0; j < i; j++) { + nums[j] = in.nextInt(); + } + nums = new int[]{2,2,3,2}; + method(nums); + + } + + public static void method(int[] nums) { + + int count = 0; + for (int i = 0; i < nums.length; i++) { + for (int j = i + 2; j < nums.length; j++) { + count += display(nums, i, j); + } + } + System.out.println(count); + } + + public static int display(int[] nums, int start, int end) { + if (end - start < 2) { + return 0; + } + HashMap map = new HashMap<>(); + for (int i = start; i <= end; i++) { + map.put(nums[i], map.getOrDefault(nums[i], 0) + 1); + if (map.keySet().size() >= 3) { + return 0; + } + } + + return 1; + } + +} + + + +class ByteDance2{ + /** + * n个事件,最大钻石数量m (1 <= n,m<= 1000) + * + * 每个事件有 x,y,z + * 有俩个选择 + * 1 消耗 x钻石 获得 y金币 + * 2 获得 z钻石 + * + * 钻石数量超出m的部分会消失,最多拥有m个钻石 + * + * 事件结束后,可以将钻石1比1换成金币 + * + * 问最多能得到多少金币 + * + * 作者:Jovanko + * 链接:https://www.nowcoder.com/feed/main/detail/e7e32ba86ff44c0aa40443c007991474?sourceSSR=search + * 来源:牛客网 + * + * 多重背包 + * @param args + */ + public static void main(String[] args) { + Scanner in = new Scanner(System.in); + int thing = in.nextInt(); + int limit = in.nextInt(); + + int[][] events = new int[thing][3]; + for (int i = 0; i < thing; i++) { + events[i][0] = in.nextInt(); + events[i][1] = in.nextInt(); + events[i][2] = in.nextInt();} + + in.close(); + + int[][] dp = new int[thing + 1][limit + 1]; + for (int i = 1; i <= thing; i++) { + int[] event = events[i - 1]; + int x = event[0]; // 消耗x + int y = event[1]; // 获得y个金币 + int z = event[2]; // 直接获取z个宝石 + for (int j = 0; j <= limit; j++) { + dp[i][j] = dp[i - 1][j]; + // 消耗宝石 + if (j >= x) { + dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - x] + y); + } + // 换宝石 + if (j + z <= limit) { + dp[i][j + z] = Math.max(dp[i][j + z], dp[i - 1][j]); + } + } + } + + int maxCoin = 0; + for (int i = 0; i <= limit; i++) { + maxCoin = Math.max(maxCoin, dp[thing][i]); + } + } + + +} + + + +class ByteDancep3{ + static int left = 0; + static int right = 0; + public static void main(String[] args) { + Scanner in = new Scanner(System.in); + int len = in.nextInt(); + int num = in.nextInt(); + int sum = 0; + int[] nums = new int[len]; + for (int i = 0; i < len; i++) { + nums[i] = in.nextInt(); + sum += nums[i]; + } + right = nums.length - 1; + + for (int i = 0; i < num; i++) { + String opr = in.next(); + Integer oprLen = Integer.valueOf(in.next()); + int value = 0; + if (oprLen > num) { + value += sum * (oprLen / len); + oprLen %= len; + } + + + if (opr.equals("L")) { + for (int j = 0; j < oprLen; j++) { + value += nums[left % len]; + left++; + } + }else { + for (int j = 0; j < oprLen; j++) { + if (right < 0) { + right = right + len; + } + value += nums[right]; + right--; + } + } + System.out.println(value); + } + + } + + public static int cut(int[] nums, String opr, int len) { + + int res = 0; + if (opr.equals("L")) { + res += calLeft(nums, left, len); + left += len; + while (left > nums.length) { + left %= nums.length; + } + }else { + res += calRight(nums, right, len); + right -= len; + while (right < 0) { + right += nums.length; + } + } + System.out.println(res); + + return res; + } + + public static int calRight(int[] nums, int end, int count) { + int res = 0; + while (count > 0) { + res += nums[end]; + end--; + count--; + if (end < 0) { + end += nums.length; + } + } + return res; + } + + public static int calLeft(int[] nums, int start, int count) { + int res = 0; + while (count >= 0) { + res += nums[start]; + start++; + count--; + if (start > nums.length) { + start -= nums.length; + } + } + return res; + } + + +} diff --git a/src/main/java/cn/whaifree/interview/qiuzhao/meituan810.java b/src/main/java/cn/whaifree/interview/qiuzhao/meituan810.java new file mode 100644 index 0000000..3b7bb88 --- /dev/null +++ b/src/main/java/cn/whaifree/interview/qiuzhao/meituan810.java @@ -0,0 +1,252 @@ +package cn.whaifree.interview.qiuzhao; + +import java.util.*; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/8/18 15:21 + * @注释 + */ +public class meituan810 { + +} + + +// 注意类名必须为 Main, 不要有任何 package xxx 信息 +class Main { + public static void main(String[] args) { + Scanner in = new Scanner(System.in); + // 注意 hasNext 和 hasNextLine 的区别 + StringBuilder sb = new StringBuilder(); + int t = in.nextInt(); + for (int i = 0; i < t; i++) { + int n = in.nextInt(); + long k = in.nextInt(); + long x = in.nextInt(); + // System.out.println("n:"+n+", k:"+k+", x:"+x); + HashSet set = new HashSet<>(); + int[] as = new int[n]; + for (int j = 0; j < n; j++) { + as[j] = in.nextInt(); + } + long min = x * n; + int cur = 0; + for (int j = n - 1; j >= 0; j--) { + set.add(as[j]); + while (set.contains(cur)) { + cur++; + } + min = Math.min(x * j + k * cur, min); + // System.out.println(set); + // System.out.println("min:"+min+", cur:"+cur); + } + sb.append(min); + sb.append("\n"); + } + System.out.println(sb.toString()); + } +} + +/*作者:逆风_前行 + 链接:https://www.nowcoder.com/exam/test/82357235/submission?examPageSource=Company&pid=58084216&testCallback=https%3A%2F%2Fwww.nowcoder.com%2Fexam%2Fcompany%3FcurrentTab%3Drecommand%26jobId%3D100%26selectStatus%3D0%26tagIds%3D179&testclass=%E8%BD%AF%E4%BB%B6%E5%BC%80%E5%8F%91 + 来源:牛客网*/ + +class p3{ + //小美有一个长度,他可以对数组进行如下操作:删除第一个元素a,同时数组的长度减一,花费为x + // 删除整个数组,花费为k×MEX(a)(其中MEX(a)表示a 中未出现过的最小非负整数。例如[0,1,2,4][0,1,2,4] 的MEX为3 + // 小美想知道将a数组全部清空的最小代价是多少,请你帮帮他吧。 + + static int allDelete; + static int oneDelete; + public static void main(String[] args) { + Scanner in = new Scanner(System.in); + int numsCount = in.nextInt(); + String[] split = in.next().split(" "); + int count = Integer.parseInt(split[0]); + allDelete = Integer.parseInt(split[1]); + oneDelete = Integer.parseInt(split[2]); + for (int i = 0; i < numsCount; i++) { + split = in.next().split(" "); + int[] ints = new int[split.length]; + for (String s : split) { + ints[i] = Integer.parseInt(s); + } + } + } + + + /** + * 4 5 2 3 1 0 + * + * 都删除 + * 删除第一个 + * @param ints + */ + public static void compute(int[] ints) { + int max = Arrays.stream(ints).max().getAsInt(); + boolean[] booleans = new boolean[max]; // 表示是否出现 + for (int i = 0; i < ints.length; i++) { + booleans[ints[i]] = true; + } + int[][] dp = new int[2][ints.length]; + /** + * dp[0] 为删除第一个元素的最小代驾 + * dp[1] 为全部删除的最小代驾 + */ + for (int i = 0; i < booleans.length; i++) { + // 如果删除第一个元素 + dp[0][i] = oneDelete; + } + } +} + +class ArrayCostCalculator { + public static void main(String[] args) { + // 4 5 2 3 1 0 + int[] array = {4, 5, 2, 3, 1, 0}; + int x = 3; // 删除第一个元素的代价 + int k = 3; // 删除整个数组的代价的系数 + int result = findMinimumCost(array, x, k); + System.out.println("The minimum cost to clear the array is: " + result); + } + + public static int findMinimumCost(int[] array, int x, int k) { + int n = array.length; // 数组长度 + int mex = findMEX(array); // 计算MEX + int costIndividualDelete = n * x; // 逐个删除的代价 + int costDeleteAll = k * mex; // 删除整个数组的代价 + return Math.min(costIndividualDelete, costDeleteAll); // 返回较小的代价 + } + + private static int findMEX(int[] array) { + int maxElement = getMaxElement(array); // 数组中的最大元素 + boolean[] 出现过 = new boolean[maxElement + 1]; // 用于跟踪数字是否出现过 + + // 标记数组中的每个元素 + for (int num : array) { + 出现过[num] = true; + } + + // 找到MEX + for (int i = 0; i <= maxElement; i++) { + if (!出现过[i]) { + return i; // 未出现的最小非负整数 + } + } + return maxElement + 1; // 如果数组包含所有数字,则MEX是最大元素加1 + } + + private static int getMaxElement(int[] array) { + int max = array[0]; + for (int num : array) { + if (num > max) { + max = num; + } + } + return max; + } +} + +class p2{ + public static void main(String[] args) { + Scanner in = new Scanner(System.in); + int num = in.nextInt(); + String right = in.next(); + TreeMap> map = new TreeMap<>(); + // map key为长度,value为数量 + for (int i = 0; i < num; i++) { + String next = in.next(); + int length = next.length(); + if (!map.containsKey(length)) { + map.put(length, new HashSet<>()); + } + map.get(length).add(next); + } + + ArrayList keys = new ArrayList<>(); + for (Integer i : map.keySet()) { + if (i < right.length()) { + keys.add(i); + } + } + +// List list = map.keySet().stream().filter(new Predicate() { +// @Override +// public boolean test(Integer integer) { +// return integer < right.length(); +// } +// }).toList(); + + int pre = 0; + for (Integer i : keys) { + pre += map.get(i).size(); + } + System.out.println(pre + 1 + " " + (pre + map.get(right.length()).size())); + + } +} +class p1{ + + + public static void main(String[] args) { + System.out.println((int) 'z'); + System.out.println((int) 'A'); + + + Scanner in = new Scanner(System.in); + // 注意 hasNext 和 hasNextLine 的区别 + int num = in.nextInt(); + for (int i = 0; i < num; i++) { + String next = in.next(); + judge(next); + } + } + + + public static void judge(String s) { + char c = s.charAt(0); + if (isEn(c)) { + // 字母开头 + boolean hasNum = false; + boolean hasEn = false; + for (int i = 1; i < s.length(); i++) { + boolean en = isEn(s.charAt(i)); + boolean num = isNum(s.charAt(i)); + if (!en && !num) { + System.out.println("invalid"); + return; + } + hasEn = hasEn || en; + hasNum = num || hasNum; + } + if (hasNum && !hasEn) { + System.out.println("standard"); + return; + } else if (!hasNum && hasEn) { + System.out.println("invalid"); + return; + } + System.out.println("mix"); + } else if (isNum(c)) { + // 数字开头 + for (int i = 1; i < s.length(); i++) { + if (!isEn(s.charAt(i))) { + System.out.println("invalid"); + return; + } + } + System.out.println("special"); + }else { + System.out.println("invalid"); + } + } + + public static boolean isNum(char c) { + return c <= '9' && c >= '0'; + } + + public static boolean isEn(char c) { + return c >= 'A' && c <= 'z'; + } +} diff --git a/src/main/java/cn/whaifree/redo/redoAll/LCR001.java b/src/main/java/cn/whaifree/redo/redoAll/LCR001.java new file mode 100644 index 0000000..23867ee --- /dev/null +++ b/src/main/java/cn/whaifree/redo/redoAll/LCR001.java @@ -0,0 +1,72 @@ +package cn.whaifree.redo.redoAll; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/8/17 22:32 + * @注释 + */ +public class LCR001 { + + public static void main(String[] args) { + + + + } + + @Test + public void test() { + + System.out.println(new Solution().divide(-2147483648, -1)); + } + + class Solution { + /** + * b<<1 + * + * 让被除数不断翻倍去近似接近 + * + * 17/3 + * 3<<1 6<<1 12<<1 (17-12=5) + * 5/3 + * + * @param a + * @param b + * @return + */ + public int divide(int a, int b) { + // 特殊情况2, b=-1 + if (b == -1) { + return a == Integer.MIN_VALUE ? Integer.MAX_VALUE : -a; + } + long A = a; + long B = b; + + + // 确定符号 + boolean positive = (A ^ B) >= 0; + // 为避免溢出, 转换为负数进行计算 -2^31 <= a, b <= 2^31 - 1 + A = A < 0 ? -A : A; + B = B < 0 ? -B : B; + + long tmpA = A; + long tmpB = B; + + long mulSum = 0; + while (tmpA >= B) { + long mul = 1; + tmpB = B; + while (tmpB << 1 < tmpA) { + tmpB <<= 1; + mul <<= 1; + } + mulSum += mul; + tmpA -= tmpB; + } + + return (int) (positive ? mulSum : -mulSum); + } + } +} diff --git a/src/main/java/cn/whaifree/redo/redoAll/LeetCode416.java b/src/main/java/cn/whaifree/redo/redoAll/LeetCode416.java new file mode 100644 index 0000000..d2122d8 --- /dev/null +++ b/src/main/java/cn/whaifree/redo/redoAll/LeetCode416.java @@ -0,0 +1,118 @@ +package cn.whaifree.redo.redoAll; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/8/17 21:33 + * @注释 + */ +public class LeetCode416 { + + @Test + public void test() + { + int[] nums = {1,5,11,5}; + System.out.println(canPartition(nums)); + } + + /** + * + * 背包容量 sum/2 11 + * 物品 nums + * + * dp[i][j]表示从0-i中任意取放入容量为j的背包的最大价值 + * + * + * dp + * 0 1 2 3 4 5 6 7 8 9 10 11 + * 0 0 1 1 1 1 1 1 1 1 1 1 1 + * 1 0 1 1 1 1 5 6 6 6 6 6 6 + * 2 0 1 1 1 1 5 6 6 6 6 6 11 + * 3 0 1 1 1 1 5 6 6 6 6 10 11 + * + * + * if 能放进去 + * 不放物品i的最大价值 dp[i-1][j] + * 放物品i的最大价值 dp[i-1][j-weight[i]] + value[i] + * else + * dp[i-1][j] + * + * @param nums + * @return + */ + public boolean canPartition(int[] nums) + { + int sum = 0; + for (int num : nums) { + sum += num; + } + if (sum % 2 == 1) { + return false; + } + + int half = sum / 2; + + int[][] dp = new int[nums.length][half + 1]; + for (int i = nums[0]; i <= half; i++) { + dp[0][i] = nums[0]; + } + + for (int i = 1; i < nums.length; i++) { + for (int j = 1; j <= half; j++) { + if (j < nums[i]) { + dp[i][j] = dp[i - 1][j]; + }else { + dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - nums[i]] + nums[i]); + /** + * 不放 dp[i-1][j] + * 放i,在i-1中获取大价值基础上加 dp[i - 1][j - nums[i]] + nums[i] + */ + } + + if (dp[i][j] == half) { + return true; + } + } + } + return false; + + } + + public boolean canPartition1(int[] nums) + { + int sum = 0; + for (int num : nums) { + sum += num; + } + if (sum % 2 == 1) { + return false; + } + + int half = sum / 2; + + int[] dp = new int[half + 1]; + for (int i = nums[0]; i <= half; i++) { + dp[i] = nums[0]; + } + + for (int i = 1; i < nums.length; i++) { + for (int j = half; j >= nums[i]; j--) { + /** + * https://www.programmercarl.com/%E8%83%8C%E5%8C%85%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%8001%E8%83%8C%E5%8C%85-2.html#%E6%80%9D%E8%B7%AF + * 如果正序遍历 + * dp[1] = dp[1 - weight[0]] + value[0] = 15 + * dp[2] = dp[2 - weight[0]] + value[0] = 30 + * 此时dp[2]就已经是30了,意味着物品0,被放入了两次,所以不能正序遍历。 + */ + dp[j] = Math.max(dp[j], dp[j - nums[i]] + nums[i]); + if (dp[j] == half) { + return true; + } + } + } + return false; + + } +} diff --git a/src/main/java/cn/whaifree/redo/redoAll/LeetCode5.java b/src/main/java/cn/whaifree/redo/redoAll/LeetCode5.java new file mode 100644 index 0000000..0bd55bc --- /dev/null +++ b/src/main/java/cn/whaifree/redo/redoAll/LeetCode5.java @@ -0,0 +1,135 @@ +package cn.whaifree.redo.redoAll; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/8/18 9:38 + * @注释 + */ +public class LeetCode5 { + + @Test + public void test() { + + System.out.println(new Solution1().longestPalindrome("cbbd")); + + } + class Solution { + /** + * dp[i][j] 表示i-j是否是回文 + * + * b a b a d + * + * 0 1 2 3 4 + * 0 1 0 1 + * 1 1 0 + * 2 1 + * 3 1 + * 4 1 + * + * if s[i]==s[j] && dp[i+1][j-1] + * + * @param s + * @return + */ + public String longestPalindrome(String s) { + char[] charArray = s.toCharArray(); + int length = s.length(); + boolean[][] dp = new boolean[length][length]; + + for (int i = 0; i < length; i++) { + dp[i][i] = true; + } + + int first = 0; + int last = 0; + for (int i = length - 1; i >= 0; i--) { + for (int j = i + 1; j < length; j++) { + if (charArray[i] == charArray[j] && (dp[i + 1][j - 1] || j == i + 1)) { + dp[i][j] = true; + if (j - i > last - first) { + first = i; + last = j; + } + } + } + } + return s.substring(first, last + 1); + } + } + + class Solution1{ + public String longestPalindrome(String s) { + + String maxLength = ""; + for (int i = 0; i < s.length(); i++) { + String s1 = maxLengthHuiWen(s, i, i + 1); + String s2 = maxLengthHuiWen(s, i, i); + if (s1.length() > maxLength.length()) { + maxLength = s1; + } + if (s2.length() > maxLength.length()) { + maxLength = s2; + } + } + return maxLength; + } + + /** + * 向外扩散的两个指针 + * + * @param s + * @param start + * @param end + * @return + */ + public String maxLengthHuiWen(String s, int start, int end) { + int length = s.length(); + while (start >= 0 && end < length) { + if (s.charAt(start) != s.charAt(end)) { + break; + } + start--; + end++; + } + return s.substring(start + 1, end); + } + + } +} + + +class LeetCode647 { + public static void main(String[] args) { + System.out.println(new Solution().countSubstrings("aaa")); + } + static class Solution { + public int countSubstrings(String s) { + char[] charArray = s.toCharArray(); + boolean[][] dp = new boolean[s.length()][s.length()]; + for (int i = 0; i < s.length(); i++) { + dp[i][i] = true; + } + + for (int i = s.length() - 1; i >= 0; i--) { + for (int j = i + 1; j < s.length(); j++) { + if (charArray[i] == charArray[j] && (j == 1 + i || dp[i + 1][j - 1])) { + dp[i][j] = true; + } + } + } + + int count = 0; + for (boolean[] booleans : dp) { + for (boolean aBoolean : booleans) { + if (aBoolean) { + count++; + } + } + } + return count; + } + } +} diff --git a/src/main/java/cn/whaifree/redo/redoAll/LeetCode713.java b/src/main/java/cn/whaifree/redo/redoAll/LeetCode713.java new file mode 100644 index 0000000..57c3afd --- /dev/null +++ b/src/main/java/cn/whaifree/redo/redoAll/LeetCode713.java @@ -0,0 +1,58 @@ +package cn.whaifree.redo.redoAll; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/8/18 23:36 + * @注释 + */ +public class LeetCode713 { + + @Test + public void test(){ + // 10,9,10,4,3,8,3,3,6,2,10,10,9,3 + int[] nums = {10,9,10,4,3,8,3,3,6,2,10,10,9,3}; + int k = 19; + System.out.println(new Solution1().numSubarrayProductLessThanK(nums, k)); + } + + class Solution { + public int numSubarrayProductLessThanK(int[] nums, int k) { + int res = 0; + for (int i = 0; i < nums.length; i++) { + int nowSum = 1; + for (int j = i; j < nums.length; j++) { + nowSum *= nums[j]; + if (nowSum < k) { + res++; + }else { + break; + } + } + } + return res; + } + } + + + class Solution1 { + public int numSubarrayProductLessThanK(int[] nums, int k) { + int res = 0; + int left = 0; + int right = 0; + int tmpSum = 1; + while (right < nums.length) { + tmpSum *= nums[right]; + while (tmpSum >= k && left <= right) { + tmpSum /= nums[left]; + left++; + } + right++; + res += right - left; + } + return res; + } + } +} diff --git a/src/main/java/cn/whaifree/test/RateLimitingRequestSplitter.java b/src/main/java/cn/whaifree/test/RateLimitingRequestSplitter.java new file mode 100644 index 0000000..d42f7aa --- /dev/null +++ b/src/main/java/cn/whaifree/test/RateLimitingRequestSplitter.java @@ -0,0 +1,121 @@ +package cn.whaifree.test; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +public class RateLimitingRequestSplitter { + + private int rateLimit; + private BlockingQueue requestQueue = new LinkedBlockingQueue<>(); + + public RateLimitingRequestSplitter(int rateLimit) { + this.rateLimit = rateLimit; + } + + public void addRequest(String request) { + requestQueue.add(request); + } + + public void processRequests() throws InterruptedException { + while (!requestQueue.isEmpty()) { + List requests = new ArrayList<>(); + for (int i = 0; i < rateLimit; i++) { + String poll = requestQueue.poll(); + if (poll == null) { + break; + } + requests.add(poll); + } + System.out.println("send requests: " + requests); + simulateRequestAndResponse(requests); + Thread.sleep(1000); + } + } + + private boolean simulateRequestAndResponse(List requests) { + // 模拟请求处理和响应,这里简单假设都成功 + try { + Thread.sleep(500); + for (int i = 0; i < requests.size(); i++) { + System.out.println("Processed request: " + requests.get(i)); + } + return true; + } catch (InterruptedException e) { + e.printStackTrace(); + return false; + } + } + + public static void main(String[] args) throws InterruptedException { + // 假设从配置中心获取的限频为 3 + int rateLimitFromConfig = 3; + RateLimitingRequestSplitter splitter = new RateLimitingRequestSplitter(rateLimitFromConfig); + + // 添加一些示例请求 + for (int i = 0; i < 100; i++) { + splitter.addRequest("Request " + i); + } + + splitter.processRequests(); + } +} + + + +class CvmResetHandler { + + private static final int MAX_CONCURRENT_REQUESTS = 5; // 最大并发请求数 + private static final int QUEUE_CAPACITY = 100; // 队列最大容量 + + private static final LinkedBlockingQueue queue = new LinkedBlockingQueue<>(QUEUE_CAPACITY); + private static final ThreadPoolExecutor executor = new ThreadPoolExecutor( + MAX_CONCURRENT_REQUESTS, MAX_CONCURRENT_REQUESTS, + 60L, TimeUnit.SECONDS, queue); + + public void resetCvm(String serverId) { + Runnable task = () -> { + try { + System.out.println("Starting to reset CVM: " + serverId); + resetCvmServer(serverId); + System.out.println("Finished resetting CVM: " + serverId); + } catch (Exception e) { + System.err.println("Error resetting CVM: " + serverId); + e.printStackTrace(); + } + }; + + // 提交任务到线程池 + executor.submit(task); + } + + private void resetCvmServer(String serverId) throws InterruptedException { + // 模拟重置操作 + Thread.sleep(new Random().nextInt(5000)); // 模拟耗时操作 + System.out.println("Resetting CVM: " + serverId); + } + + public static void main(String[] args) { + CvmResetHandler handler = new CvmResetHandler(); + + // 创建多个重置请求 + for (int i = 0; i < 50; i++) { + String serverId = "server-" + i; + handler.resetCvm(serverId); + } + + // 等待所有任务完成 + executor.shutdown(); + try { + if (!executor.awaitTermination(60, TimeUnit.SECONDS)) { + System.err.println("Some tasks did not complete in time."); + } + } catch (InterruptedException e) { + System.err.println("Interrupted while waiting for tasks to complete."); + } + } +}