该程序用于读取文件,并将每一行作为HTTP发送。文件中的每一行都是一个 URL。
例如 http://localhost:8080/?a=1&b=2
PoolingClientConnectionManager pcm = new PoolingClientConnectionManager();
pcm.setMaxTotal(200);
pcm.setDefaultMaxPerRoute(20);
HttpClient client = new DefaultHttpClient(pcm);
ExecutorService executorService = Executors.newFixedThreadPool(10);
try (BufferedReader bfrDataSource = new BufferedReader(new FileReader(path))) {
while((line=bfrDataSource.readLine()) != null){
executorService.execute(new SendTask(line, client));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
executorService.shutdown();
client.getConnectionManager().shutdown();
发送任务.java
public class SendTask implements Runnable {
private String url;
private final HttpClient client;
public SendTask(String url, HttpClient client){
this.url = url;
this.client = client;
}
@Override
public void run() {
HttpGet httpGet = new HttpGet(url);
try {
HttpResponse response = client.execute(httpGet);
response.getEntity().getContent().close();
} catch (ClientProtocolException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
} finally{
httpGet.abort();
}
}
}
当我发送 500,000 行的文件时,它可以工作。但随后它发送了 100,000 行,发生了一个错误:java.lang.OutOfMemoryError:超出了 GC 开销限制。
- 如何修改程序以确保它可以发送至少 100 万行? 谢谢!
Executors.newFixedThreadPool() 创建的线程池由一个无限队列支持,当您向其提交新任务并且没有可用的工作线程时,它会将任务缓存在队列中。这就是您获得 OOM 异常的原因。
若要修复此问题,需要使用具有有界工作队列的线程池:
ExecutorService executorService = new ThreadPoolExecutor(10, 10, 0, TimeUnit.SECONDS, new SynchronousQueue<Runnable>());
可以使用各种队列实现,但在您的情况下,同步队列应该就足够了。
此外,您应该在工作线程完成其工作后关闭 httpclient:
httpclient.getConnectionManager().shutdown();
查看 httpclient javadoc 了解详细信息。