内存不足 - 在 Java 中发送批量 HTTP



该程序用于读取文件,并将每一行作为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 了解详细信息。

相关内容

  • 没有找到相关文章

最新更新