Java-如何在排队等待其他请求时一次发送一定数量的http请求
我正在开发一个discord机器人,它允许您使用JihanRESTAPI为myanimelist搜索动画。但是,API每秒只允许2个请求,任何违反该要求的行为都将导致IP禁令。因此,我必须将搜索函数(它将请求发送到JihanAPI)编程为一次只搜索两件事。然而,这比看起来要复杂得多 对于那些不知道Discord API是如何工作的人,有一个重写的message received方法,每当位于包含bot的服务器上的用户发送消息时,就会运行该方法。这个方法也有点像线程,因为每个发送消息的用户都会运行一个单独的实例 这会使程序复杂化,因为如果有3个以上的用户同时搜索一部动画,我需要在排队等待第三部动画的同时发送两个请求,直到另外两个中的一个返回响应。但是,我还必须将该响应返回给发送它的Java-如何在排队等待其他请求时一次发送一定数量的http请求,java,httprequest,discord,Java,Httprequest,Discord,我正在开发一个discord机器人,它允许您使用JihanRESTAPI为myanimelist搜索动画。但是,API每秒只允许2个请求,任何违反该要求的行为都将导致IP禁令。因此,我必须将搜索函数(它将请求发送到JihanAPI)编程为一次只搜索两件事。然而,这比看起来要复杂得多 对于那些不知道Discord API是如何工作的人,有一个重写的message received方法,每当位于包含bot的服务器上的用户发送消息时,就会运行该方法。这个方法也有点像线程,因为每个发送消息的用户都会运行
messageReceived
方法的实例
我真的没有任何代码可以显示。对于如何解决这个问题,我只希望能有一个解释、伪代码或java代码。多谢各位我不确定我是否完全正确地解决了您的问题,但似乎您可以使用消费者/生产者模式解决这个问题,并在两者之间设置阻塞队列 因此,当用户发送消息时,它不会直接发送到JihanRESTAPI,而是作为任务提交到阻塞队列。这将是应用程序的一部分 消费者部分将通过获取队列的任务(用户消息)并发送请求来提交给JihanRESTAPI 通过将可调用项提交到包含两个线程的有界线程池,您可以确保每秒只提交和返回两个请求。由于Callable将一直阻塞到它完成为止,所以您可以在这两个过程之间留出一秒钟的时间。
或者你可以使用一个像信号灯这样的同步器,这将是一个更好的实践。我看到了ilot的反应,我同意他的建议。他已经提到使用信号量将是一个好主意,我想我将分享一个使用该库的Java示例。我没有任何不和谐的经验,但希望你或其他人会发现这个例子很有用
import java.util.concurrent.Semaphore;
public class SemaphoreDemo {
final static int TOTAL_REQUESTS = 10;
final static int MAX_SIMULTANEOUS_REQUESTS = 2;
final Semaphore semaphore;
// the purpose of this array is for synchronization of the demo only
final Thread[] threads = new Thread[TOTAL_REQUESTS];
public static void main(String[] args) throws InterruptedException {
new SemaphoreDemo().start();
}
SemaphoreDemo() {
semaphore = new Semaphore(MAX_SIMULTANEOUS_REQUESTS);
}
void start() throws InterruptedException {
System.out.printf("Start sending... [permits = %d]\n", semaphore.availablePermits());
// trigger incoming messages
for (int i = 0; i < TOTAL_REQUESTS; i++) {
messageReceived(new Request(i));
}
// synchronize with threads
for (int i = 0; i < TOTAL_REQUESTS; i++) {
threads[i].join();
}
System.out.println("Done!");
}
void messageReceived(Request request) {
RequestHandler requestHandler = new RequestHandler(request, semaphore);
Thread thread = createThread(request.i, requestHandler);
thread.start();
}
Thread createThread(int i, RequestHandler requestHandler) {
threads[i] = new Thread(requestHandler);
return threads[i];
}
}
class Request {
final int i;
Request(int i) {
this.i = i;
}
void sendHttpRequest() {
// do your thing
}
@Override
public String toString() {
return "Request " + i;
}
}
class RequestHandler implements Runnable {
final Request request;
final Semaphore semaphore;
RequestHandler(Request request, Semaphore semaphore) {
this.request = request;
this.semaphore = semaphore;
}
@Override
public void run() {
try {
// try to acquire one of the permits if available, else wait...
semaphore.acquire();
System.out.printf("%s: sending request [permits = %d]\n", request, semaphore.availablePermits());
// Simulate sending a request with a random response time between 0 and 3 seconds
request.sendHttpRequest();
Thread.sleep(Math.round(3000 * Math.random()));
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
// the request succeeded or was interrupted; always release the permit so another request can take it
semaphore.release();
System.out.printf("%s: received response [permits = %d]\n", request, semaphore.availablePermits());
}
}
}
请注意,请求可能会按顺序结束,但总有0到2个可用许可证
Start sending... [permits = 2]
Request 0: sending request [permits = 1]
Request 1: sending request [permits = 0]
Request 1: received response [permits = 1]
Request 2: sending request [permits = 0]
Request 2: received response [permits = 1]
Request 3: sending request [permits = 0]
Request 0: received response [permits = 1]
Request 4: sending request [permits = 0]
Request 3: received response [permits = 1]
Request 5: sending request [permits = 0]
Request 4: received response [permits = 1]
Request 6: sending request [permits = 0]
Request 5: received response [permits = 1]
Request 7: sending request [permits = 0]
Request 6: received response [permits = 1]
Request 8: sending request [permits = 0]
Request 8: received response [permits = 1]
Request 9: sending request [permits = 0]
Request 9: received response [permits = 1]
Request 7: received response [permits = 2]
Done!