在日常的 Java 开发工作中,我们常常会遇到这样的需求:要对不同的接口进行独立的任务处理,以确保它们不会相互干扰。最近我就遇到了类似的问题,并且成功找到了一种解决方案,下面就跟大家分享一下。
问题背景
在我的项目里,之前所有的接口任务都被放在同一个消息队列里处理。这就导致了一个问题,不同接口的任务可能会相互影响,比如某个接口的任务处理时间过长,就会影响到其他接口的响应速度。所以,我希望能够将某些接口的任务放在一个消息队列中,而另外一些接口的任务放在另一个消息队列中,以此实现接口之间的隔离。
解决方案
为了解决这个问题,我对原有的消息队列进行了改造,实现了支持多个消息队列的功能。下面是具体的实现步骤和代码。
封装消息队列类
首先,我创建了一个 CustomMessageQueue
类,将消息队列和线程池封装在一起,方便管理。以下是这个类的代码:
import java.util.concurrent.*;
// 自定义消息队列类
public class CustomMessageQueue {
// 使用 LinkedBlockingQueue 存储任务
private final LinkedBlockingQueue<Runnable> taskQueue = new LinkedBlockingQueue<>();
// 创建一个固定大小的线程池
private final ExecutorService executorService;
public CustomMessageQueue(int threadPoolSize) {
this.executorService = Executors.newFixedThreadPool(threadPoolSize);
// 启动一个线程来处理队列中的任务
executorService.submit(() -> {
while (true) {
try {
// 从队列中取出任务并执行
Runnable task = taskQueue.take();
task.run();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
}
// 向队列中添加任务的方法
public void addTask(Runnable task) {
try {
taskQueue.put(task);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
// 关闭线程池
public void shutdown() {
executorService.shutdown();
}
}
在这个类中,taskQueue
用于存储任务,executorService
是一个固定大小的线程池,负责处理队列中的任务。通过构造函数传入线程池的大小,然后启动一个线程不断从队列中取出任务并执行。
创建多个消息队列实例
接下来,我在控制器类中创建了两个不同的消息队列实例,分别用于处理不同接口的任务。以下是示例代码:
import java.util.concurrent.CountDownLatch;
// 假设的返回结果类
class R {
private String message;
public R(String message) {
this.message = message;
}
public static R error(String message) {
return new R(message);
}
@Override
public String toString() {
return message;
}
}
// 示例控制器类
public class ControllerExample {
// 创建两个不同的消息队列实例
private static final CustomMessageQueue queue1 = new CustomMessageQueue(1);
private static final CustomMessageQueue queue2 = new CustomMessageQueue(1);
// 假设的请求和请求头类
class Request {}
class RequestHead {}
// 处理请求的方法
private R handleGetPhoneurls(Request request, RequestHead requesthead) {
// 模拟处理请求
return R.error("模拟处理请求");
}
// 接口 1 使用队列 1
public R interface1(Request request, RequestHead requesthead) {
CountDownLatch latch = new CountDownLatch(1);
final R[] result = new R[1];
queue1.addTask(() -> {
try {
result[0] = handleGetPhoneurls(request, requesthead);
} catch (Exception e) {
result[0] = R.error("请求出错: " + e.getMessage());
} finally {
latch.countDown();
}
});
try {
latch.await();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return R.error("请求被中断");
}
return result[0];
}
// 接口 2 使用队列 2
public R interface2(Request request, RequestHead requesthead) {
CountDownLatch latch = new CountDownLatch(1);
final R[] result = new R[1];
queue2.addTask(() -> {
try {
result[0] = handleGetPhoneurls(request, requesthead);
} catch (Exception e) {
result[0] = R.error("请求出错: " + e.getMessage());
} finally {
latch.countDown();
}
});
try {
latch.await();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return R.error("请求被中断");
}
return result[0];
}
public static void main(String[] args) {
ControllerExample controller = new ControllerExample();
Request request = controller.new Request();
RequestHead requestHead = controller.new RequestHead();
R result1 = controller.interface1(request, requestHead);
R result2 = controller.interface2(request, requestHead);
System.out.println("接口 1 结果: " + result1);
System.out.println("接口 2 结果: " + result2);
// 关闭消息队列
queue1.shutdown();
queue2.shutdown();
}
}
在这个示例中,ControllerExample
类包含两个接口方法 interface1
和 interface2
,分别使用 queue1
和 queue2
来处理任务。通过 CountDownLatch
来确保任务执行完成后再返回结果。
总结
通过这种方式,我们成功实现了不同接口使用不同消息队列的功能,有效地解决了接口之间相互干扰的问题。希望这篇博客能对大家在处理类似问题时有所帮助。
以上就是本次分享的全部内容,如果你有任何疑问或者建议,欢迎在评论区留言交流。