- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
在 Android 上,某些回调始终按设计在主 Thread
上调用,例如以下 ServiceConnection
:
private Completable dismissService() {
return Completable.fromEmitter(new Action1<CompletableEmitter>() {
@Override
public void call(final CompletableEmitter completableEmitter) {
final ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// here always main Thread...
unbindService(this);
completableEmitter.onCompleted();
}
@Override
public void onServiceDisconnected(ComponentName name) {
// no-op
}
};
completableEmitter.setCancellation(new AsyncEmitter.Cancellable() {
@Override
public void cancel() throws Exception {
unbindService(conn);
}
});
bindService(new Intent(MainActivity.this, MyService.class), conn, BIND_AUTO_CREATE);
}
});
}
但是,我希望 dismissService()
返回的 Completable 在调用它的任何 Thread
上发出它的结果。我使用 newSingleThreadExecutor()
尝试了以下(hacky?)解决方案:
private Completable dismissServiceRetainingThread() {
return Single.fromCallable(new Callable<Thread>() {
@Override
public Thread call() throws Exception {
return Thread.currentThread();
}
}).flatMapCompletable(new Func1<Thread, Completable>() {
@Override
public Completable call(final Thread thread) {
return Completable.fromEmitter(new Action1<CompletableEmitter>() {
@Override
public void call(final CompletableEmitter completableEmitter) {
final ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// here always main Thread...
unbindService(this);
completableEmitter.onCompleted();
}
@Override
public void onServiceDisconnected(ComponentName name) {
// no-op
}
};
completableEmitter.setCancellation(new AsyncEmitter.Cancellable() {
@Override
public void cancel() throws Exception {
unbindService(conn);
}
});
bindService(new Intent(MainActivity.this, MyService.class), conn, BIND_AUTO_CREATE);
}
}).observeOn(Schedulers.from(
Executors.newSingleThreadExecutor(
new ThreadFactory() {
@Override
public Thread newThread(@NonNull Runnable runnable) {
return thread;
}
}
)));
}
});
}
但是,这会因以下 IllegalThreadStateException
而崩溃:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.jenzz.rxjavathreadingtest, PID: 5307
java.lang.IllegalThreadStateException
at java.util.concurrent.ThreadPoolExecutor.addWorker(ThreadPoolExecutor.java:930)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1348)
at java.util.concurrent.Executors$DelegatedExecutorService.execute(Executors.java:591)
at rx.internal.schedulers.ExecutorScheduler$ExecutorSchedulerWorker.schedule(ExecutorScheduler.java:79)
at rx.Completable$28$1.onCompleted(Completable.java:1805)
at rx.internal.operators.CompletableFromEmitter$FromEmitter.onCompleted(CompletableFromEmitter.java:73)
at com.jenzz.rxjavathreadingtest.MainActivity$5$2$1.onServiceConnected(MainActivity.java:117)
关于如何跳回到之前在上游使用的原始 Thread
的任何想法,例如使用 subscribeOn(Schedulers.io())
?
最佳答案
您不想返回到您所在的确切线程。当同一个 Scheduler
中的其他线程空闲时,它可能很忙,除非它是主线程,否则无法保证它在回调返回时仍然存在。一旦您的 call
方法返回,它就可以用于更多工作或清理。我认为您想要的是在与原始调用相同的 Scheduler
上执行。 AFIAK,也没有直接的方法来确定线程的当前 Scheduler
(有一种确定某些调度程序的脆弱方法,在本文底部提到)。所以你不能轻易地做你想做的事。默认在主线程上通知似乎是此方法的理智行为。如果您希望它默认为不同的 Scheduler
,您可以添加 .observeOn(Schedulers.io())
或您选择的调度程序。
如另一个答案所述,如果当前线程有一个循环程序,您可以尝试创建一个 Handler
。您仍然会依赖调用者来确保回调发生时线程仍然可行。与告诉调用者响应将出现在主线程上相比,这似乎是一种更高级别的责任,除非他们使用 observesOn
选择不同的响应。
作为最后的想法,可以通过查看线程的名称来为 Schedulers
返回的标准调度程序确定正确的调度程序。它们具有可预测的前缀,例如 RxNewThreadScheduler-1
,因此一些 String.startsWith()
调用可以隔离正确的调度。不过,这非常脆弱,因为它无法正确处理用户创建的调度程序,并且线程命名方案将来可能会发生变化。
关于java - RxJava : How to retain Thread from upstream,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40900349/
完成此任务的最佳方法是什么:主线程(线程 A)创建另外两个线程(线程 B 和线程 C)。线程 B 和 C 执行繁重的磁盘 I/O,最终需要将它们创建的资源传递给线程 A,然后调用外部 DLL 文件中的
我是一名对 Julia 语言感兴趣的新手程序员。文档( https://docs.julialang.org/en/v1/base/multi-threading/ )说 Threads.@threa
python中的thread.start_new_thread和threading.Thread.start有什么区别? 我注意到,当调用 start_new_thread 时,新线程会在调用线程终止
我正在学习安卓蓝牙编程。我从 Google 的 Android 开发者网站上复制了大部分代码以供学习。这个想法是监听服务器上的连接是在一个新线程中完成的,而不会阻塞 UI 线程。当收到连接请求时,连接
执行对象方法的线程是否依赖于创建它的线程上的线程? 假设您的 java 应用程序中有两个线程 Thread1 和 Thread2,以及两个类 ClassA 和 ClassB。 您在 Thread1 上
我正在用这段代码测试 C++11 线程,但是在创建线程时,我遇到了错误没有匹配函数调用 'std::thread::thread()'. 这就像我给 std::thread ctr 的函数有什么问题,
我有如下类 eventEngine 和网关: class eventEngine { public: eventEngine(); std::thread threa; std
我需要运行与列表 dirlist 中的元素一样多的 Observer 类线程。当我运行它 python 控制台时,它可以正常工作。 class Observer(Thread): def ru
我在一本 Java 书中读到了下面的代码。我知道主类默认继承 Thread 类,所以 currentThread();而不是 Thread.currentThread();也会做这项工作。 但我不明白
我在我的系统中使用第 3 方 API,该 API 启动一个永久运行的用户线程。一旦我的程序结束,JVM 由于该线程而继续运行,因此我尝试获取此线程引用并通过更改它 thread.setDaemon(t
我所知道的 Python 中的每个对象都可以通过调用来处理其基类初始化: super(BaseClass, self).__init__() threading.Thread 的子类似乎不是这种情况,
在我最近从事的 Xamarin 项目中,我可以看到开发人员使用了 Java.Lang.Thread 以及 System.Threading.Thread(用于非常相似的操作 - 例如在后台加载数据)。
我在 Julia 中运行双循环。代码非常简单。 w = rand(1000,1000) function regular_demo(w::Array{Float64, 2}) n = size
我在 Windows 上使用 Python 3。我正在使用 threading.Thread动态运行一个函数,我可以带参数或不带参数调用它。我正在设置一个列表,其中的第一项是定义路径的字符串。其他参数
我遇到了一些使用线程模块(使用 Python 2.6)管理线程的示例。 我想了解的是这个例子是如何调用“运行”方法的,在哪里调用的。我在任何地方都看不到它。 ThreadUrl 类在 main() 函
假设我从 threading.Thread 派生: from threading import Thread class Worker(Thread): def start(self):
关闭。这个问题需要debugging details .它目前不接受答案。 编辑问题以包含 desired behavior, a specific problem or error, and th
使用 WinDbg 和 SOS,我有以下内容: 0:011> !threads ThreadCount: 7 UnstartedThread: 0 BackgroundThread: 4 Pendin
App Engine 给出错误: com.google.apphosting.api.ApiProxy$CallNotFoundException: Can't make API call urlfe
我正在尝试将 Swing JEditorPane 嵌入到 JavaFX 项目中,如下代码所示。 Platform.runLater(() -> { SyntaxTester ob = new
我是一名优秀的程序员,十分优秀!