newCachedThreadPool()中的线程总是在等待,线程数总是在增加

时间:2013-02-21 09:40:55

标签: java threadpool nio out-of-memory

我遇到了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将收到的数据发送到另一台服务器,相关代码:

的servlet:

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状态使得池认为线程是所有“忙”,所以需要创建新的线程。

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

先谢谢,凯尔文


编辑:最后我发现根本原因是因为http请求需要很长时间才能响应,所以如果以突发方式提交任务,则线程数将始终增加,因为一个任务需要很长时间才能完成。

0 个答案:

没有答案