工人/背景线程“窒息”UI线程Android-为什么?

时间:2016-05-01 19:12:36

标签: java android multithreading

所以当在AsyncTask派生类里面的doInBackground()中运行以下方法时:

void waitUntilButtonClicked(){
            while(true){
            synchronized (buttonClicked){
                if(buttonClicked) return;
                                        }
                try{Thread.sleep(1);} catch(InterruptedException e){};

                             }

没有使后台线程休眠1毫秒的最后一行代码,用户界面不起作用(有一个EditText小部件,当点击时根本没有响应)。我应该提一下,当waitUntilButtonClicked()运行时,UI线程不运行任何东西(或者不是我的任何代码)。

我的问题是我必须添加最后一行才能正常工作。 我认为后台线程无法阻止UI线程,除非程序员的部分存在巨大错误。  为什么会这样?是的,我已经找到了解决这个问题的“方法”,我的解决方案是一种常用的方法吗?还有更好的方法吗?

1 个答案:

答案 0 :(得分:1)

  

为什么会这样?

你正在a busy spin loop中占用CPU,使CPU周期的其他所有内容都匮乏。

  

是的,我已经找到了解决这个问题的'方法',我的解决方案是一种常用的方法吗?

不,如sleeping to make a busy spin loop less busy generally is considered to be poor form

  

有更好的方法吗?

考虑到您的代码,我们假设您有一个Button,并且当点击Button时,您希望在后台线程中工作。

如果是这种情况,您可以:

  • Button

  • onClick()点击Button后,只分叉线程
  • 维护一个线程池(例如Executors.newSingleThreadExecutor()),并将作业发布到onClick()

  • Button中的该线程池
  • 使用startService()IntentService的{​​{1}}启动onClick() Button IntentService的工作onHandleIntent() (在后台线程上调用)

  • HandlerThread

  • post()使用onClick()Button个事件
  • 使用中级阻止机制,例如CountDownLatchSemaphore,您可以通过boolean

  • 使用严重的低级别阻止机制,例如Object#wait()

可能还有其他选择,但这六个选项将是一个很好的起点。所有这些情况都使用操作系统级别的阻塞原语将线程标记为必要时暂停,而不是每隔毫秒不必要地唤醒线程。