### Question:
MainThreadDisposable implements Disposable { @Override public final void dispose() { if (unsubscribed.compareAndSet(false, true)) { if (Looper.myLooper() == Looper.getMainLooper()) { onDispose(); } else { AndroidSchedulers.mainThread().scheduleDirect(this::onDispose); } } }  static void verifyMainThread(); @Override final boolean isDisposed(); @Override final void dispose();  }### Answer:
@Test public void onUnsubscribeRunsSyncOnMainThread() { ShadowLooper.pauseMainLooper(); final AtomicBoolean called = new AtomicBoolean(); new MainThreadDisposable() { @Override protected void onDispose() { called.set(true); } }.dispose(); assertTrue(called.get()); }
@Test public void unsubscribeTwiceDoesNotRunTwice() { final AtomicInteger called = new AtomicInteger(0); Disposable disposable = new MainThreadDisposable() { @Override protected void onDispose() { called.incrementAndGet(); } }; disposable.dispose(); disposable.dispose(); disposable.dispose(); assertEquals(1, called.get()); }
@Test public void onUnsubscribePostsOffMainThread() throws InterruptedException { ShadowLooper.pauseMainLooper(); final CountDownLatch latch = new CountDownLatch(1); final AtomicBoolean called = new AtomicBoolean(); new Thread(new Runnable() { @Override public void run() { new MainThreadDisposable() { @Override protected void onDispose() { called.set(true); } }.dispose(); latch.countDown(); } }).start(); assertTrue(latch.await(1, SECONDS)); assertFalse(called.get()); ShadowLooper.runMainLooperOneTask(); assertTrue(called.get()); }