okhttp3:无法创建新的本机线程
okhttp3 : unable to create new native thread
遇到一个奇怪的问题,试了几次都无法重现。如何重现它以及它为什么会发生?
非并发任务,循环调用HTTP连接
public static Response syncGet(URL url) throws IOException {
log.debug("http url:{}", url);
OkHttpClient client = new OkHttpClient().newBuilder().connectTimeout(15L, TimeUnit.SECONDS)
.readTimeout(30L, TimeUnit.SECONDS).build();
Request request = new Request.Builder().url(url).get().addHeader("cache-control", "no-cache").build();
Call call = client.newCall(request);
return call.execute();
}
堆栈:
2019-12-05 11:20:56.068 ERROR 18484 --- [ scheduling-1] o.s.s.s.TaskUtils$LoggingErrorHandler : Unexpected error occurred in scheduled task
java.lang.OutOfMemoryError: unable to create new native thread
at java.lang.Thread.start0(Native Method) [na:1.8.0_181]
at java.lang.Thread.start(Thread.java:717) [na:1.8.0_181]
at java.util.concurrent.ThreadPoolExecutor.addWorker(ThreadPoolExecutor.java:957) [na:1.8.0_181]
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1378) [na:1.8.0_181]
at okhttp3.ConnectionPool.put(ConnectionPool.java:153) ~[okhttp-3.12.1.jar:na]
at okhttp3.OkHttpClient.put(OkHttpClient.java:167) ~[okhttp-3.12.1.jar:na]
at okhttp3.internal.connection.StreamAllocation.findConnection(StreamAllocation.java:266) ~[okhttp-3.12.1.jar:na]
at okhttp3.internal.connection.StreamAllocation.findHealthyConnection(StreamAllocation.java:135) ~[okhttp-3.12.1.jar:na]
at okhttp3.internal.connection.StreamAllocation.newStream(StreamAllocation.java:114) ~[okhttp-3.12.1.jar:na]
at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:42) ~[okhttp-3.12.1.jar:na]
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147) ~[okhttp-3.12.1.jar:na]
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121) ~[okhttp-3.12.1.jar:na]
at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93) ~[okhttp-3.12.1.jar:na]
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147) ~[okhttp-3.12.1.jar:na]
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121) ~[okhttp-3.12.1.jar:na]
at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93) ~[okhttp-3.12.1.jar:na]
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147) ~[okhttp-3.12.1.jar:na]
at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:126) ~[okhttp-3.12.1.jar:na]
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147) ~[okhttp-3.12.1.jar:na]
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121) ~[okhttp-3.12.1.jar:na]
at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:254) ~[okhttp-3.12.1.jar:na]
at okhttp3.RealCall.execute(RealCall.java:92) ~[okhttp-3.12.1.jar:na]
at chances.cms.util.HttpUtil.syncGet(HttpUtil.java:67) ~[classes/:na]
at chances.cms.task.CheckTask.checkContent(CheckTask.java:76) ~[classes/:na]
at chances.cms.task.CheckTask.check(CheckTask.java:60) ~[classes/:na]
at chances.cms.task.CheckTask.check(CheckTask.java:51) ~[classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_181]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_181]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_181]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_181]
at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:84) ~[spring-context-5.2.1.RELEASE.jar:5.2.1.RELEASE]
at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) ~[spring-context-5.2.1.RELEASE.jar:5.2.1.RELEASE]
at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:93) [spring-context-5.2.1.RELEASE.jar:5.2.1.RELEASE]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [na:1.8.0_181]
at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_181]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access1(ScheduledThreadPoolExecutor.java:180) [na:1.8.0_181]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) [na:1.8.0_181]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_181]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_181]
at java.lang.Thread.run(Thread.java:748) [na:1.8.0_181]
OkHttpClients should be shared
OkHttp performs best when you create a single OkHttpClient instance and reuse it for all of your HTTP calls. This is because each client holds its own connection pool and thread pools. Reusing connections and threads reduces latency and saves memory.
more detail: https://square.github.io/okhttp/3.x/okhttp/okhttp3/OkHttpClient.html
因此在 syncGet
方法之外创建 client
应该可以解决您的问题。
遇到一个奇怪的问题,试了几次都无法重现。如何重现它以及它为什么会发生?
非并发任务,循环调用HTTP连接
public static Response syncGet(URL url) throws IOException {
log.debug("http url:{}", url);
OkHttpClient client = new OkHttpClient().newBuilder().connectTimeout(15L, TimeUnit.SECONDS)
.readTimeout(30L, TimeUnit.SECONDS).build();
Request request = new Request.Builder().url(url).get().addHeader("cache-control", "no-cache").build();
Call call = client.newCall(request);
return call.execute();
}
堆栈:
2019-12-05 11:20:56.068 ERROR 18484 --- [ scheduling-1] o.s.s.s.TaskUtils$LoggingErrorHandler : Unexpected error occurred in scheduled task java.lang.OutOfMemoryError: unable to create new native thread at java.lang.Thread.start0(Native Method) [na:1.8.0_181] at java.lang.Thread.start(Thread.java:717) [na:1.8.0_181] at java.util.concurrent.ThreadPoolExecutor.addWorker(ThreadPoolExecutor.java:957) [na:1.8.0_181] at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1378) [na:1.8.0_181] at okhttp3.ConnectionPool.put(ConnectionPool.java:153) ~[okhttp-3.12.1.jar:na] at okhttp3.OkHttpClient.put(OkHttpClient.java:167) ~[okhttp-3.12.1.jar:na] at okhttp3.internal.connection.StreamAllocation.findConnection(StreamAllocation.java:266) ~[okhttp-3.12.1.jar:na] at okhttp3.internal.connection.StreamAllocation.findHealthyConnection(StreamAllocation.java:135) ~[okhttp-3.12.1.jar:na] at okhttp3.internal.connection.StreamAllocation.newStream(StreamAllocation.java:114) ~[okhttp-3.12.1.jar:na] at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:42) ~[okhttp-3.12.1.jar:na] at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147) ~[okhttp-3.12.1.jar:na] at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121) ~[okhttp-3.12.1.jar:na] at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93) ~[okhttp-3.12.1.jar:na] at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147) ~[okhttp-3.12.1.jar:na] at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121) ~[okhttp-3.12.1.jar:na] at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93) ~[okhttp-3.12.1.jar:na] at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147) ~[okhttp-3.12.1.jar:na] at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:126) ~[okhttp-3.12.1.jar:na] at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147) ~[okhttp-3.12.1.jar:na] at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121) ~[okhttp-3.12.1.jar:na] at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:254) ~[okhttp-3.12.1.jar:na] at okhttp3.RealCall.execute(RealCall.java:92) ~[okhttp-3.12.1.jar:na] at chances.cms.util.HttpUtil.syncGet(HttpUtil.java:67) ~[classes/:na] at chances.cms.task.CheckTask.checkContent(CheckTask.java:76) ~[classes/:na] at chances.cms.task.CheckTask.check(CheckTask.java:60) ~[classes/:na] at chances.cms.task.CheckTask.check(CheckTask.java:51) ~[classes/:na] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_181] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_181] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_181] at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_181] at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:84) ~[spring-context-5.2.1.RELEASE.jar:5.2.1.RELEASE] at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) ~[spring-context-5.2.1.RELEASE.jar:5.2.1.RELEASE] at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:93) [spring-context-5.2.1.RELEASE.jar:5.2.1.RELEASE] at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [na:1.8.0_181] at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_181] at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access1(ScheduledThreadPoolExecutor.java:180) [na:1.8.0_181] at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) [na:1.8.0_181] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_181] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_181] at java.lang.Thread.run(Thread.java:748) [na:1.8.0_181]
OkHttpClients should be shared
OkHttp performs best when you create a single OkHttpClient instance and reuse it for all of your HTTP calls. This is because each client holds its own connection pool and thread pools. Reusing connections and threads reduces latency and saves memory.
more detail: https://square.github.io/okhttp/3.x/okhttp/okhttp3/OkHttpClient.html
因此在 syncGet
方法之外创建 client
应该可以解决您的问题。