应用偶现某个页面加载不出来,但是又不崩溃的情况,排查原因记录
public T executeSync(@Nullable Queue queue, @NonNull IDbOptProxy<T> opt) {
if (checkExecuteOrigin(queue)) {
return opt.executeOpt();
}
final DbOptCallback<T> callback = new DbOptCallback<>();
DbOptLogger logger = new DbOptLogger();
assert queue != null;
Rx2QueueUtil.backgroundTaskOnMain(queue, () -> {
callback.onResult(opt.executeOpt());
logger.tick();
return 0;
}, null).subscribe();
while (!callback.optDone()) {
SystemClock.sleep(1);
}
logger.end();
CLog.d(TAG, "[sync] %s", logger.getLog());
return callback.getResult();
}
private static <T> Observable<T> backgroundTaskOnMain(@NonNull Scheduler scheduler, @NonNull Callable<T> callable,
@Nullable LifeEndOwner owner) {
Observable<T> observable = Observable.fromCallable(callable)
.subscribeOn(scheduler)
.observeOn(AndroidSchedulers.mainThread());
if (owner != null) {
observable = observable.compose(owner.bindToEnd2());
}
return observable;
}
这段代码实现了一个将耗时的任务放到单独的后台线程执行,并在执行完成后回调到主线程的功能。executeSync方法接受一个线程名和一个opt参数,其中线程名用于指定后台线程的名称,opt参数是一个实现了OptCallback接口的回调对象,用于执行耗时任务并在执行完成后回调。
在executeSync方法内部,首先通过Rx2QueueUtil.getQueue方法获取一个线程名为queueName的线程,并将opt封装成一个Callable对象。然后,调用Rx2QueueUtil.backgroundTaskOnMain方法,将该Callable对象在queueName线程上执行,并将执行结果发布到主线程上的Observable对象中。最后,通过Observable的阻塞方法blockingFirst获取执行结果,并将结果返回给executeSync方法的调用者。
如果在多线程环境下,多个线程同时调用executeSync方法,可能会出现死锁问题。例如,如果线程A调用executeSync方法,将任务放到线程B执行,并在等待执行结果时被阻塞;同时,线程B在执行任务前也调用了executeSync方法,将任务放到线程A执行,并在等待执行结果时被阻塞,那么就会发生死锁。