1

我遇到了tomcat抛出的问题OutOfMemoryError

SEVERE: Servlet.service() for servlet DataPortServlet threw exception
java.lang.OutOfMemoryError: unable to create new native thread
    at java.lang.Thread.start0(Native Method)
    at java.lang.Thread.start(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor.addIfUnderMaximumPoolSize(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor.execute(Unknown Source)
    at java.util.concurrent.AbstractExecutorService.submit(Unknown Source)
    ...

我要做的是:当在servlet中接收到数据时,将接收到的数据通过HttpClient相关代码发送到另一台服务器:

小服务程序:

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
    ...
    byte[] data = getDataFromRequest(request); // pseudo code, get data
    CallableLogSender sender = new CallableLogSender(data);
    pool.submit(sender); // here the pool is the one instantiated at the start of application, singleton
    ...
}

类实现Callable接口:

public class CallableLogSender implements Callable<Integer> {
    private byte[] content;

    public CallableLogSender(byte[] content) {
        this.content = content;
    }

    @Override
    public Integer call() {
        try {
            String uri = getRemoteServerUri(); // pseudo code, get uri here
            HttpPost request = new HttpPost(uri);
            request.setHeader("Content-Type", "application/x-www-form-urlencoded");
            request.setEntity(new ByteArrayEntity(content));

            HttpClient httpClient = getHttpClient(); // pseudo code, get cached http client, it is a singleton instance
            HttpResponse response = httpClient.execute(request);
            statusCode = response.getStatusLine().getStatusCode();
            EntityUtils.consume(response.getEntity());
        } catch(Exception e) {
            // log error here...
        } finally {
            request.releaseConnection();
        }
        return statusCode;
    }
}

如代码所示,submit每次有客户端连接时,我对线程池进行了一个任务,然后我使用jProfiler监控tomcat,它显示池中的线程数一直在增加!并且所有线程都处于waiting状态,所以当线程数超过阈值时,OutOfMemoryError就会发生。

在我看来,线程应该重用,线程数应该稳定,至少不会一直增加,不知道是不是因为waiting状态让池认为线程都“忙”了,所以new thread需要创建。

那么关于如何使池重用线程而不总是创建新线程的任何建议?

提前致谢, 开尔文


编辑:最后我找到根本原因是因为http请求响应时间太长,所以如果任务是突发提交的,线程数会一直在增加,因为一个任务完成时间太长。

4

0 回答 0