而在实际开发中,我们需要为网络请求相关代码单独开启一个子线程,将网络请求代码运行在这个子线程中,当网络请求结束返回数据并开始更新UI界面时,我们需要将线程切换回主线程后才能去更新UI界面,否则就会报错(android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6838)) 这段话的意思其实就是我们只可以在主线程中更新UI,当我们在其他线程中更新UI时,就会抛出这个异常。
public final class ObservableSubscribeOn extends AbstractObservableWithUpstream{
}
发现它继承了AbstractObservableWithUpstream这个类
/**
* Base class for operators with a source consumable.
*
* @param the input source type
* @param the output type
*/
abstract class AbstractObservableWithUpstream extends Observable implements HasUpstreamObservableSource {
/** The source consumable Observable. */
protected final ObservableSource source;
/**
* Constructs the ObservableSource with the given consumable.
* @param source the consumable Observable
*/
AbstractObservableWithUpstream(ObservableSource source) {
this.source = source;
}
@Override
public final ObservableSource source() {
return source;
}
}
/**
* Represents a basic, non-backpressured {@link Observable} source base interface,
* consumable via an {@link Observer}.
*
* @param the element type
* @since 2.0
*/
public interface ObservableSource {
/**
* Subscribes the given Observer to this ObservableSource instance.
* @param observer the Observer, not null
* @throws NullPointerException if {@code observer} is null
*/
void subscribe(@NonNull Observer super T> observer);
}
3、在ObservableSubscribeOn类的subscribeActual(final Observer super T> s)方法中(这个方法接收的observer参数是从下游传递过来的),将外部传进来的observer对象用SubscribeOnObserver内部类包装起来(保存在其成员变量actual中)得到该内部类的一个对象parent(通过SubscribeOnObserver parent = new SubscribeOnObserver(s),这个内部类主要用于辅助订阅线程切换)。
public final class Schedulers {
@NonNull
static final Scheduler SINGLE;
@NonNull
static final Scheduler COMPUTATION;
@NonNull
static final Scheduler IO;
@NonNull
static final Scheduler TRAMPOLINE;
@NonNull
static final Scheduler NEW_THREAD;
static final class SingleHolder {
static final Scheduler DEFAULT = new SingleScheduler();
}
static final class ComputationHolder {
static final Scheduler DEFAULT = new ComputationScheduler();
}
static final class IoHolder {
static final Scheduler DEFAULT = new IoScheduler();
}
static final class NewThreadHolder {
static final Scheduler DEFAULT = new NewThreadScheduler();
}
static {
SINGLE = RxJavaPlugins.initSingleScheduler(new SingleTask());
COMPUTATION = RxJavaPlugins.initComputationScheduler(new ComputationTask());
IO = RxJavaPlugins.initIoScheduler(new IOTask());
TRAMPOLINE = TrampolineScheduler.instance();
NEW_THREAD = RxJavaPlugins.initNewThreadScheduler(new NewThreadTask());
}
//......代码省略
}
static final class EventLoopWorker extends Scheduler.Worker {
private final CompositeDisposable tasks;
private final CachedWorkerPool pool;
private final ThreadWorker threadWorker;
//保存订阅状态
final AtomicBoolean once = new AtomicBoolean();
EventLoopWorker(CachedWorkerPool pool) {
this.pool = pool;
this.tasks = new CompositeDisposable();
this.threadWorker = pool.get();
}
//取消订阅时,释放当前的threadWorker
@Override
public void dispose() {
//如果成功的将disposed状态设置为true,则取消订阅,并将释放当前的threadWorker资源,并将其添加到Worker管理池中
if (once.compareAndSet(false, true)) {
tasks.dispose();
// releasing the pool should be the last action
pool.release(threadWorker);
}
}
@Override
public boolean isDisposed() {
return once.get();
}
@NonNull
@Override
public Disposable schedule(@NonNull Runnable action, long delayTime, @NonNull TimeUnit unit) {
if (tasks.isDisposed()) {
// don't schedule, we are unsubscribed
return EmptyDisposable.INSTANCE;
}
//实际线程调度工作
return threadWorker.scheduleActual(action, delayTime, unit, tasks);
}
}
虽然EventLoopWorker也继承了Scheduler的内部类Worker,但在scheduler方法中,把实际的线程调度工作转发给了ThreadWorker去进行,ThreadWorker又继承了NewThreadWorker类,我们点进scheduleActual(action, delayTime, unit, tasks)方法看下(该方法位于NewThreadWorker类中):
@NonNull
public ScheduledRunnable scheduleActual(final Runnable run, long delayTime, @NonNull TimeUnit unit, @Nullable DisposableContainer parent) {
Runnable decoratedRun = RxJavaPlugins.onSchedule(run);
//1、包装类,管理任务线程,内部实现了一系列方法,包括线程任务的执行,设置任务标志位,任务的取消等。
//这个parent参数就是我们平常使用的CompositeDisposable对象,负责订阅批量管理
ScheduledRunnable sr = new ScheduledRunnable(decoratedRun, parent);
if (parent != null) {
if (!parent.add(sr)) {
return sr;
}
}
Future> f;
try {
//2、将任务线程ScheduledRunnable放入线程池执行任务,根据是否有延迟时间调用相应的方法
if (delayTime <= 0) {
f = executor.submit((Callable
既然返回的是ScheduledRunnable对象,我们就来看下这个类:
//这里即实现了Runnable接口也实现了Callable接口,用于应对需要返回值和不需要返回值的情况
public final class ScheduledRunnable extends AtomicReferenceArray implements Runnable, Callable, Disposable {
private static final long serialVersionUID = -6120223772001106981L;
final Runnable actual;
/** Indicates that the parent tracking this task has been notified about its completion. */
static final Object PARENT_DISPOSED = new Object();
/** Indicates the dispose() was called from within the run/call method. */
static final Object SYNC_DISPOSED = new Object();
/** Indicates the dispose() was called from another thread. */
static final Object ASYNC_DISPOSED = new Object();
static final Object DONE = new Object();
//保存追踪该任务的外部任务状态的标识
static final int PARENT_INDEX = 0;
//保存该任务运行状态的标识
static final int FUTURE_INDEX = 1;
//保存其他线程像该任务发出的指令标识
static final int THREAD_INDEX = 2;
/**
* Creates a ScheduledRunnable by wrapping the given action and setting
* up the optional parent.
* @param actual the runnable to wrap, not-null (not verified)
* @param parent the parent tracking container or null if none
*/
public ScheduledRunnable(Runnable actual, DisposableContainer parent) {
super(3);
this.actual = actual;
//如果我们在外部通过一个disposable容器来管理当前任务,就保存这个disposable容器
this.lazySet(0, parent);
}
@Override
public Object call() {
// Being Callable saves an allocation in ThreadPoolExecutor
run();
return null;
}
@Override
public void run() {
//设置任务执行线程为当前所在线程
lazySet(THREAD_INDEX, Thread.currentThread());
try {
try {
//执行实际IO任务
actual.run();
} catch (Throwable e) {
// Exceptions.throwIfFatal(e); nowhere to go
RxJavaPlugins.onError(e);
}
} finally {
//任务执行期间出现错误,重置当前执行线程为null
lazySet(THREAD_INDEX, null);
//获取追踪次任务的外部任务状态
Object o = get(PARENT_INDEX);
if (o != PARENT_DISPOSED && compareAndSet(PARENT_INDEX, o, DONE) && o != null) {
//如果追踪该任务状态的外部任务还没有被终止,将它设置为DONE状态,并将当前任务从订阅状态管理容器中删除
((DisposableContainer)o).delete(this);
}
//任务在执行出错时,确保任务的执行结果状态为SYNC_DISPOSED,ASYNC_DISPOSED以及DONE中的任意一个即可
for (;;) {
o = get(FUTURE_INDEX);
if (o == SYNC_DISPOSED || o == ASYNC_DISPOSED || compareAndSet(FUTURE_INDEX, o, DONE)) {
break;
}
}
}
}
//设置Runnable任务的运行状态
public void setFuture(Future> f) {
for (;;) {
Object o = get(FUTURE_INDEX);
if (o == DONE) {
return;
}
if (o == SYNC_DISPOSED) {
f.cancel(false);
return;
}
if (o == ASYNC_DISPOSED) {
f.cancel(true);
return;
}
if (compareAndSet(FUTURE_INDEX, o, f)) {
return;
}
}
}
//结束Runnable任务运行
@Override
public void dispose() {
for (;;) {
//获取任务运行状态
Object o = get(FUTURE_INDEX);
//如果任务执行结果状态为以下三个状态中的任意一个,表示任务已被结束,什么也不做
if (o == DONE || o == SYNC_DISPOSED || o == ASYNC_DISPOSED) {
break;
}
//判断任务在执行期间所在的线程以及执行终止后所在的线程是否一致
boolean async = get(THREAD_INDEX) != Thread.currentThread();
//设置该任务是在同步环境下结束的还是在异步环境下结束的
if (compareAndSet(FUTURE_INDEX, o, async ? ASYNC_DISPOSED : SYNC_DISPOSED)) {
if (o != null) {
//取消任务的执行
((Future>)o).cancel(async);
}
break;
}
}
for (;;) {
//获取追踪该任务的外部任务所处状态
Object o = get(PARENT_INDEX);
if (o == DONE || o == PARENT_DISPOSED || o == null) {
//如果外部任务状态是终止状态,则什么也不做
return;
}
if (compareAndSet(PARENT_INDEX, o, PARENT_DISPOSED)) {
//如果外部任务状态不是终止状态,将其设置为终止状态,并将当前任务从状态容器中移除
((DisposableContainer)o).delete(this);
return;
}
}
}
//根据追踪该任务的父任务状态并根据父任务是否结束来判断该任务是否结束
@Override
public boolean isDisposed() {
Object o = get(PARENT_INDEX);
return o == PARENT_DISPOSED || o == DONE;
}
}
原题链接:#137 Single Number II
要求:
给定一个整型数组,其中除了一个元素之外,每个元素都出现三次。找出这个元素
注意:算法的时间复杂度应为O(n),最好不使用额外的内存空间
难度:中等
分析:
与#136类似,都是考察位运算。不过出现两次的可以使用异或运算的特性 n XOR n = 0, n XOR 0 = n,即某一
A message containing letters from A-Z is being encoded to numbers using the following mapping:
'A' -> 1
'B' -> 2
...
'Z' -> 26
Given an encoded message containing digits, det