抽象算法
有一个消息发送接口MessageService.send(String message),每次消息发送需要耗时2ms;
基于以上接口,实现一个批量发送接口MessageService.batchSend(List<String> messages);
要求如下:
1)一次批量发送消息最大数量为100条
2)批量发送接口一次耗时不超过50ms。
3)要求返回消息发送是否成功的结果。
import java.util.List;
import java.util.concurrent.*;
public class MessageService {
// 模拟单条消息发送
public static boolean send(String message) {
try {
// 模拟发送消息的时间消耗
Thread.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
return false;
}
return true;
}
// 批量发送消息
public static boolean batchSend(List<String> messages) {
int maxBatchSize = 100; // 一次批量发送消息最大数量为100条
int totalMessages = messages.size();
int threadCount = 4; // 使用4个线程
if (totalMessages > maxBatchSize) {
throw new IllegalArgumentException("一次批量发送消息最大数量为100条");
}
ExecutorService executor = Executors.newFixedThreadPool(threadCount);
CompletionService<Boolean> completionService = new ExecutorCompletionService<>(executor);
CountDownLatch latch = new CountDownLatch(totalMessages);
boolean[] results = new boolean[totalMessages];
// 提交任务
for (int i = 0; i < totalMessages; i++) {
final int index = i;
completionService.submit(() -> {
boolean result = send(messages.get(index));
latch.countDown();
return result;
});
}
// 收集结果
try {
for (int i = 0; i < totalMessages; i++) {
Future<Boolean> future = completionService.poll(50, TimeUnit.MILLISECONDS);
if (future != null) {
results[i] = future.get();
} else {
return false; // 如果在50ms内未完成,返回失败
}
}
executor.shutdown();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
return false;
}
for (boolean result : results) {
if (!result) {
return false; // 如果任何一条消息发送失败,返回失败
}
}
return true; // 所有消息发送成功
}
public static void main(String[] args) {
// 测试批量发送
List<String> messages = List.of(new String[100]); // 创建100条空消息
boolean result = batchSend(messages);
System.out.println("消息发送结果: " + (result ? "成功" : "失败"));
}
}
某用户请求某接口信息,控制该接口在单位时间内透出次数,单位时间和次数是提前定义好的
package com.example.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.time.Duration;
import java.util.Optional;
@Component
public class RateLimitFilter extends OncePerRequestFilter {
@Autowired
private StringRedisTemplate redisTemplate;
private static final Duration TIME_WINDOW = Duration.ofMinutes(1); // 时间窗口
private static final long MAX_REQUESTS = 100; // 最大请求次数
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain)
throws ServletException, IOException {
String userId = request.getHeader("userId");
if (userId == null || "".equals(userId)) {
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
return;
}
String key = "requests:user:" + userId + ":" + TIME_WINDOW.toMillis();
Long currentRequests = Optional.ofNullable(redisTemplate.opsForValue().increment(key))
.map(Long::valueOf).orElse(1L);
if (currentRequests <= MAX_REQUESTS) {
filterChain.doFilter(request, response);
} else {
response.setStatus(HttpServletResponse.SC_TOO_MANY_REQUESTS);
response.getWriter().write("Too many requests");
}
// 设置过期时间
redisTemplate.expire(key, TIME_WINDOW.toMillis(), TimeUnit.MILLISECONDS);
}
}
Comments NOTHING