面试题答案
一键面试设计思路
- 使用Java NIO:Java NIO(New I/O)提供了基于通道(Channel)和缓冲区(Buffer)的I/O操作方式,其非阻塞特性可以有效提升I/O效率,适用于大量并发请求场景。
- 线程池:创建线程池来管理并发请求,避免频繁创建和销毁线程带来的开销。合理设置线程池大小可以根据系统资源(如CPU核心数、内存等)进行调整,以充分利用系统资源同时避免资源耗尽。
- 连接池:对于HTTP请求,使用连接池来复用HTTP连接,减少每次请求建立新连接的开销。
- 异步处理:利用Java的Future或CompletableFuture实现异步处理,在发起请求后不阻塞主线程,继续执行其他任务,待结果返回时再进行处理。
核心代码片段
以下是使用Java NIO和线程池实现高效并发HTTP请求的核心代码示例:
- 引入依赖(如果使用HttpClient库):
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
</dependency>
- 创建线程池:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class HttpConcurrentRequest {
private static final int THREAD_POOL_SIZE = 10;
private static final ExecutorService executorService = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
}
- 发起HTTP请求:
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import java.io.IOException;
import java.util.concurrent.Callable;
public class HttpTask implements Callable<HttpResponse> {
private final String url;
public HttpTask(String url) {
this.url = url;
}
@Override
public HttpResponse call() throws Exception {
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(url);
try {
return httpClient.execute(httpGet);
} catch (IOException e) {
throw new RuntimeException("Failed to execute HTTP request", e);
} finally {
try {
httpClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
- 提交任务并获取结果:
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
public class HttpConcurrentRequest {
private static final int THREAD_POOL_SIZE = 10;
private static final ExecutorService executorService = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
public static void main(String[] args) {
List<String> urls = new ArrayList<>();
// 添加多个URL
urls.add("http://example.com");
urls.add("http://another-example.com");
List<Future<HttpResponse>> futures = new ArrayList<>();
for (String url : urls) {
HttpTask task = new HttpTask(url);
futures.add(executorService.submit(task));
}
for (Future<HttpResponse> future : futures) {
try {
HttpResponse response = future.get();
// 处理响应
System.out.println("Response status: " + response.getStatusLine());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
executorService.shutdown();
}
}
在上述代码中:
- 首先创建了一个固定大小的线程池
executorService
,用于管理并发任务。 HttpTask
类实现了Callable
接口,负责发起HTTP请求并返回响应。- 在
main
方法中,将多个URL的请求任务提交到线程池,并通过Future
获取每个请求的响应结果,从而实现并发请求和异步处理。最后关闭线程池以释放资源。