worker/后台线程"smothers" UI 线程 Android - 为什么?



因此,当在AsyncTask派生类内部的doInBackground()中运行以下方法时:

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

如果没有让后台线程睡眠1毫秒的最后一行代码,用户界面就无法工作(有一个EditText小部件,当点击它时根本没有响应)。我应该提到,当waitUntilButtonClicked()运行时,UI线程不会运行任何东西(或者更确切地说,不会运行我的任何代码)。

我的问题是,我必须添加最后一行才能使所有内容都工作。我认为后台线程不能阻塞UI线程,除非程序员出现了巨大的错误。为什么会发生这种情况?是的,我已经找到了克服这一问题的"方法",我的解决方案是一种常见的方法吗?有更好的方法吗?

为什么会发生这种情况?

您将CPU占用在繁忙的旋转循环中,使其他一切都失去了CPU周期。

是的,我已经找到了克服这一问题的"方法",我的解决方案是一种常见的方法吗?

不,因为睡眠使繁忙的旋转循环不那么繁忙通常被认为是糟糕的形式

有更好的方法吗?

让我们假设,给定您的代码,您有一个Button,当单击Button时,您希望在后台线程中进行工作。

如果是这样的话,你可以:

  • ButtononClick()中,单击Button后仅分叉线程

  • 维护一个线程池(例如,Executors.newSingleThreadExecutor()),并将作业发布到onClick()中的该线程池中,用于Button

  • 使用startService()Button启动onClick()中的IntentService,其中IntentServiceonHandleIntent()(在后台线程上调用)中执行工作

  • 对于Button ,从onClick()向其使用HandlerThreadpost()事件

  • 使用中级阻塞机制,如CountDownLatchSemaphore,以这种方式触发后台线程,而不是通过boolean

  • 认真使用低级别的阻塞机制,如Object#wait()

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

最新更新