1

该程序用于读取文件,并将每一行作为 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 万行?谢谢你!
4

1 回答 1

1

Executors.newFixedThreadPool() 创建的线程池由一个无界队列支持,当你向它提交新任务并且没有可用的工作线程时,它会将任务缓存在队列中。这就是你得到OOM异常的原因。

要修复它,您需要使用具有有界工作队列的线程池:

ExecutorService executorService = new ThreadPoolExecutor(10, 10, 0, TimeUnit.SECONDS, new SynchronousQueue<Runnable>());

可以使用各种队列实现,但是在您的情况下, SynchronousQueue 应该就足够了。

此外,您应该在工作人员完成工作后关闭 httpclient:

httpclient.getConnectionManager().shutdown();

检查httpclient javadoc了解详细信息。

于 2013-01-29T05:07:17.760 回答