因此,当在 AsyncTask 派生类内部的 doInBackground() 中运行以下方法时:
void waitUntilButtonClicked(){
while(true){
synchronized (buttonClicked){
if(buttonClicked) return;
}
try{Thread.sleep(1);} catch(InterruptedException e){};
}
如果没有最后一行代码使后台线程 hibernate 1 毫秒,用户界面将无法工作(有一个 EditText 小部件,点击它时根本不会响应)。我应该提到,当 waitUntilButtonClicked() 运行时,UI 线程不会运行任何内容(或者更确切地说,不会运行我的任何代码)。
我的问题是我必须添加最后一行才能使一切正常工作。 我认为后台线程不能阻塞 UI 线程,除非程序员出现了巨大的错误。 为什么会发生这种情况?是的,我已经找到了一种克服这个问题的“方法”,我的解决方案是一种常见的方法吗?有更好的办法吗?
最佳答案
Why does it happen?
您正在 a busy spin loop 中占用 CPU ,让其他所有 CPU 周期都处于饥饿状态。
And yes I've figured out a 'way' to overcome that, is my solution a common method of doing that?
否,如 sleeping to make a busy spin loop less busy generally is considered to be poor form .
Is there a better way?
假设给定您的代码,您有一个 Button
,当 Button
单击后,您想在后台线程中执行工作。
如果是这种情况,您可以:
仅在
Button
出现一次后 fork 线程单击,在onClick()
对于Button
维护一个线程池(例如
Executors.newSingleThreadExecutor()
),并将作业发布到onClick()
中的该线程池。对于Button
使用
startService()
启动IntentService
在onClick()
对于Button
,其中IntentService
工作在onHandleIntent()
(在后台线程上调用)使用
HandlerThread
和post()
来自onClick()
的事件对于Button
使用中级阻止机制,例如
CountDownLatch
或Semaphore
,您可以通过这种方式触发后台线程,而不是通过boolean
使用严格的低级阻止机制,例如
Object#wait()
可能还有其他选择,但这六个将是一个很好的起点。所有这些情况都使用操作系统级阻塞原语将线程标记为挂起,直到有必要为止,而不是每毫秒不必要地唤醒线程的方法。
关于java - 工作线程/后台线程 "smothers"UI 线程 Android - 为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36970806/