[英]Worker/Background Thread “smothers” UI thread Android- Why?
So when running the following method in doInBackground() inside of AsyncTask derived class: 因此,在AsyncTask派生类内部的doInBackground()中运行以下方法时:
void waitUntilButtonClicked(){
while(true){
synchronized (buttonClicked){
if(buttonClicked) return;
}
try{Thread.sleep(1);} catch(InterruptedException e){};
}
without the very last line of code which makes the background thread sleep for 1 ms, the User Interface doesn't work (there is an EditText widget which when tapped on doesn't respond at all). 如果没有最后一行代码使后台线程休眠1 ms,则用户界面将不起作用(有一个EditText小部件,当点击该按钮时根本不响应)。 I should mention that when waitUntilButtonClicked() runs the UI thread doesn't run anything (or rather not any of my code).
我应该提到的是,当waitUntilButtonClicked()运行时,UI线程不会运行任何东西(或者不是我的任何代码)。
My problem is that I HAD to add the last line for everything to work. 我的问题是我不得不为所有工作添加最后一行。 I thought that a background thread cannot block the UI thread unless there is a huge error on the programmer's part.
我以为后台线程不能阻止UI线程,除非程序员方面有很大的错误。 Why does it happen?
为什么会发生? And yes I've figured out a 'way' to overcome that, is my solution a common method of doing that?
是的,我已经找到了解决该问题的“方法”,我的解决方案是这样做的常用方法吗? Is there a better way?
有没有更好的办法?
Why does it happen?
为什么会发生?
You are tying up the CPU in a busy spin loop , starving everything else of CPU cycles. 您正在忙碌的旋转循环中占用CPU,从而耗尽了CPU周期的所有其他时间。
And yes I've figured out a 'way' to overcome that, is my solution a common method of doing that?
是的,我已经找到了解决该问题的“方法”,我的解决方案是这样做的常用方法吗?
No, as sleeping to make a busy spin loop less busy generally is considered to be poor form . 不,因为睡觉使忙碌的自旋循环不那么忙,通常被认为是不良的形式 。
Is there a better way?
有没有更好的办法?
Let's assume, given your code, that you have a Button
, and when the Button
is clicked, you want to do work in a background thread. 让我们假设,在给定代码的情况下,您拥有一个
Button
,并且在单击Button
时,您想要在后台线程中工作。
If that is the case, you could: 如果是这样,您可以:
Only fork the thread once the Button
is clicked, in the onClick()
for the Button
只有用叉子叉线,一旦
Button
被点击时,在onClick()
的Button
Maintain a thread pool (eg, Executors.newSingleThreadExecutor()
), and post a job to that thread pool in the onClick()
for the Button
维护一个线程池(例如
Executors.newSingleThreadExecutor()
),然后在Button
的onClick()
中将作业发布到该线程池中
Use startService()
to kick off an IntentService
in the onClick()
for the Button
, where the IntentService
does the work in onHandleIntent()
(which is called on a background thread) 使用
startService()
在Button
的onClick()
启动一个IntentService
,其中IntentService
在onHandleIntent()
中进行工作onHandleIntent()
在后台线程上调用)
Use a HandlerThread
and post()
events to it from onClick()
for the Button
使用
HandlerThread
并将onClick()
中的post()
事件添加到该Button
Use mid-level blocking mechanisms, like CountDownLatch
or Semaphore
, where you trigger your background thread that way instead of via the boolean
使用中级阻止机制,例如
CountDownLatch
或Semaphore
,在其中以这种方式触发后台线程,而不是通过boolean
Use seriously low-level blocking mechanisms, like Object#wait()
使用严重的低级阻止机制,例如
Object#wait()
Probably there are other options as well, but those six would be a good starting point. 也许还有其他选择,但是那六个是一个很好的起点。 All of these cases use OS-level blocking primitives to mark a thread as suspended until necessary, rather than your approach of waking up the thread unnecessarily every millisecond.
所有这些情况都使用OS级阻塞原语来将线程标记为已暂停,直到必要为止,而不是使用您不必要地每毫秒唤醒一次线程的方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.