Android Rxjava+;内存错误抛出的改进

Android Rxjava+;内存错误抛出的改进,android,Android,当我使用rxjava进行改造时,一些机器会发出声音,这是日志: java.lang.IllegalStateException: Fatal Exception thrown on Scheduler.Worker thread. at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:59) at java.util.concurrent.Executors$RunnableAdapter.call(Executor

当我使用rxjava进行改造时,一些机器会发出声音,这是日志:

java.lang.IllegalStateException: Fatal Exception thrown on Scheduler.Worker thread.
at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:59)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:152)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:265)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:818)
Caused by: java.lang.OutOfMemoryError: pthread_create (1040KB stack) failed: Try again
at java.lang.Thread.nativeCreate(Native Method)
at java.lang.Thread.start(Thread.java:1063)
at java.util.concurrent.ThreadPoolExecutor.addWorker(ThreadPoolExecutor.java:920)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1338)
at okhttp3.ConnectionPool.put(ConnectionPool.java:135)
at okhttp3.OkHttpClient$1.put(OkHttpClient.java:149)
at okhttp3.internal.connection.StreamAllocation.findConnection(StreamAllocation.java:188)
at okhttp3.internal.connection.StreamAllocation.findHealthyConnection(StreamAllocation.java:129)
at okhttp3.internal.connection.StreamAllocation.newStream(StreamAllocation.java:98)
at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:42)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:109)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:124)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
at okhttp3.logging.HttpLoggingInterceptor.intercept(HttpLoggingInterceptor.java:145)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:170)
at okhttp3.RealCall.execute(RealCall.java:60)
at retrofit2.OkHttpCall.execute(OkHttpCall.java:174)
at retrofit2.adapter.rxjava.RxJavaCallAdapterFactory$RequestArbiter.request(RxJavaCallAdapterFactory.java:171)
at rx.internal.operators.OperatorSubscribeOn$1$1$1.request(OperatorSubscribeOn.java:80)
at rx.Subscriber.setProducer(Subscriber.java:209)
at rx.internal.operators.OperatorSubscribeOn$1$1.setProducer(OperatorSubscribeOn.java:76)
at rx.Subscriber.setProducer(Subscriber.java:205)
at retrofit2.adapter.rxjava.RxJavaCallAdapterFactory$CallOnSubscribe.call(RxJavaCallAdapterFactory.java:152)
at retrofit2.adapter.rxjava.RxJavaCallAdapterFactory$CallOnSubscribe.call(RxJavaCallAdapterFactory.java:138)
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
at rx.Observable.unsafeSubscribe(Observable.java:9861)
at rx.internal.operators.OperatorSubscribeOn$1.call(OperatorSubscribeOn.java:94)
at rx.internal.schedulers.CachedThreadScheduler$EventLoopWorker$1.call(CachedThreadScheduler.java:221)
at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422) 
at java.util.concurrent.FutureTask.run(FutureTask.java:237) 
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:152) 
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:265) 
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) 
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) 
at java.lang.Thread.run(Thread.java:818) 
我的改装代码:

  HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
    if (BuildConfig.LOG_DEBUG)
        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
    else
        interceptor.setLevel(HttpLoggingInterceptor.Level.NONE);
    OkHttpClient client = new OkHttpClient.Builder()
            .addInterceptor(interceptor)
            .retryOnConnectionFailure(true)
            .connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
            .readTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
            .build();

    retrofit = new Retrofit.Builder()
            .baseUrl(ConstantValue.URL + "/")
            .client(client)
            .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
            .build();
和我的请求代码:

public interface GetUserFriendUsersService {

@FormUrlEncoded
@POST("IM/GetUserFriendUsers")
Observable<ResponseBody> getUserFriendUsers(@Field("UserID")String UserID);}

 public void getUserFriendUsers(String userID, Subscriber<List<Users>> subscriber) {
    retrofit.create(GetUserFriendUsersService.class)
            .getUserFriendUsers(userID)
            .subscribeOn(Schedulers.io())
            .unsubscribeOn(Schedulers.io())
            .map(new HttpResultFunc())
            .map(new Func1<JSONObject, List<Users>>() {
                @Override
                public List<Users> call(JSONObject jsonObject) {
                    List<Users> users = JSON.parseArray(jsonObject.getString("users"), Users.class);
                    if (users.size() == 0)
                        throw new CustomizeException("no data");
                    return users;
                }
            })
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(subscriber);
}
公共接口GetUserFriendUsersService{
@FormUrlEncoded
@POST(“IM/GetUserFriendUsers”)
可观察的getUserFriendUsers(@Field(“UserID”)字符串UserID);}
public void getUserFriendUsers(字符串userID,订户){
create(GetUserFriendUsersService.class)
.getUserFriendUsers(用户ID)
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.map(新的HttpResultFunc())
.map(新函数1(){
@凌驾
公共列表调用(JSONObject JSONObject){
List users=JSON.parseArray(jsonObject.getString(“用户”),users.class);
if(users.size()==0)
抛出新的CustomizeException(“无数据”);
返回用户;
}
})
.observeOn(AndroidSchedulers.mainThread())
.认购(认购人);
}

这个.observeOn()应该在map()前面,在unsubscribeOn()后面。

在github上发布了相同的问题

问题是Schedulers.io()使用缓存线程池而没有限制,因此试图创建1500个线程。您应该考虑使用具有固定线程限制的调度器,或者使用RxJava 2 .x的并行()操作符将操作并行化为固定数量的工作人员。 如果您在默认情况下使用原始改装,它将使用OkHttp的dispatcher,它将线程限制为64个(每个主机最多5个)。这就是为什么你没有看到它失败的原因

如果在创建RxJava2CallAdapterFactory时使用createAsync(),它将创建完全异步的可观察实例,这些实例不需要subscribeOn,并且使用OkHttp的Dispatcher,就像改型一样。然后您只需要observeOn移回主线程,就可以避免所有额外的线程创建