简体   繁体   中英

Worker/Background Thread “smothers” UI thread Android- Why?

So when running the following method in doInBackground() inside of AsyncTask derived class:

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). I should mention that when waitUntilButtonClicked() runs the UI thread doesn't run anything (or rather not any of my code).

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. 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.

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.

If that is the case, you could:

  • Only fork the thread once the Button is clicked, in the onClick() for the Button

  • Maintain a thread pool (eg, Executors.newSingleThreadExecutor() ), and post a job to that thread pool in the onClick() for the Button

  • 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)

  • Use a HandlerThread and post() events to it from onClick() for the Button

  • Use mid-level blocking mechanisms, like CountDownLatch or Semaphore , where you trigger your background thread that way instead of via the boolean

  • Use seriously low-level blocking mechanisms, like 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM