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)
    ...

私がやりたいことは、サーブレットでデータを受信すると、受信したデータを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私の意見では、スレッドを再利用する必要があり、スレッド番号は安定している必要があります。少なくとも常に増加するとは限りません。状態がプールにスレッドがすべて「ビジー」であると思わせるためかどうかはわかりません。したがって、新しいスレッド作成する必要があります。

では、プールでスレッドを再利用し、常に新しいスレッドを作成するのではなくする方法について何か提案はありますか?

よろしくお願いします、ケルビン


編集: 最後に、根本的な原因は、http 要求の応答に時間がかかりすぎるためであることがわかりました。そのため、タスクがバーストで送信されると、1 つのタスクが完了するのに時間がかかりすぎるため、スレッド数が常に増加します。

4

0 に答える 0