Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/215.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 处理程序与线程之间是否存在任何真正的性能影响?_Android - Fatal编程技术网

Android 处理程序与线程之间是否存在任何真正的性能影响?

Android 处理程序与线程之间是否存在任何真正的性能影响?,android,Android,关于线程与处理程序与异步任务的正确使用,存在许多问题。(如&) 这些问题很好地解决了何时使用什么的问题。我的问题更多的是在某些类型的情况下对性能的影响 例如,我经常看到其他人编写代码时使用线程,只是为了能够为将来安排一些代码执行。每当我看到这一点时,我本能地想重构代码,使用处理程序,只需发布延迟的可运行的 下面是一个例子,其中一个线程用于更新使用mediaplayer播放的某些媒体的seekbar,然后是我将使用的方法 我经常看到的: if (positionTracker != null &

关于
线程
处理程序
异步任务
的正确使用,存在许多问题。(如&)

这些问题很好地解决了何时使用什么的问题。我的问题更多的是在某些类型的情况下对性能的影响

例如,我经常看到其他人编写代码时使用
线程
,只是为了能够为将来安排一些代码执行。每当我看到这一点时,我本能地想重构代码,使用
处理程序
,只需发布延迟的
可运行的

下面是一个例子,其中一个线程用于更新使用
mediaplayer
播放的某些媒体的seekbar,然后是我将使用的方法

我经常看到的:

 if (positionTracker != null && positionTracker.isAlive()
                && !positionTracker.isInterrupted()) {
            return;
        }

        positionTracker = new Thread(new Runnable() {

            public void run() {
                int currentPosition = 0;
                int total = player.getDuration();
                while (player != null && CurrentPosition < total) {
                    try {
                        Thread.sleep(1000);
                        currentPosition = player.getCurrentPosition();
                    } catch (InterruptedException e) {
                        return;
                    } catch (Exception e) {
                        return;
                    }


                    if (someListener != null) {
                        someListener.onEvent();
                    }

                }
            }

        }, "position tracker thread");

        positionTracker.start();
Runnable trackPositionRunnable = new Runnable() {
            @Override
            public void run() {
                currentPosition = player.getCurrentPosition();
                if (someListener != null) {
                    someListener.onEvent();
                    mHandler.postDelayed(this, 1000);
                }
            }
        };

        mHandler.post(trackPositionRunnable);

显然,我更喜欢的方式是更容易阅读和更简洁但性能影响是什么?就性能而言,一种方法比另一种方法更好吗?如果是,原因是什么?

正确性:您的第一个示例充满了危险,因为必须在具有自己的
循环器的线程上创建
MediaPlayer
,来自任何其他线程的操作都可能导致错误。类似地,由于您的
someListener.onEvent()
可能正在更新UI,因此最好知道如何将其发布到UI线程上的处理程序

性能:我没有提供任何度量,但在您的示例中,运行时成本是(线程切换)+(处理程序开销),而不是(处理程序开销)。因此,对于任何切换开销大于0的线程,线程的开销都会更高。另一方面,如果您的整个应用程序都是以您喜欢的风格编写的,并且您的任何代码都是缓慢和同步的,那么您只会让您的应用程序感觉滞后


这就是为什么任何可能缓慢或同步的东西都需要转向线程(或服务)风格,尽管感觉更复杂、更容易出错。您特定的MediaPlayer示例并不是一个完美的例子。

每种方法都取决于您计划在该可运行环境中执行的操作,以及它是否有用。它们之间最大的区别在于你是否打算触摸UI。在安卓系统中,用户界面组件不能脱离用户界面线程(你的媒体播放器示例就是用原始线程打破这一规则)。因为这条规则会立即划分每个方法可以做什么和不能做什么。这些方法之间的性能差异可以忽略不计,因为运行后台作业所花费的时间将胜过它们之间的任何差异

处理程序通常使用另一个后台线程来执行中的逻辑,但这取决于由哪个线程构造处理程序。如果处理程序是在UI线程上构造的(响应对某些内容的回调),那么您的Runnable将在UI线程内运行,从而可以触摸UI组件。但是,如果您是在UI线程之外创建的,则发布到它的Runnables无法接触UI组件。在UI线程上创建的处理程序的缺点是,您没有在后台执行这些操作,因此,如果作业需要很长时间才能运行,它将锁定UI,直到完成为止。而从非UI线程运行的处理程序将修复锁定UI的任何问题。它们需要更多的工作来设置,并且您仍然需要处理如何安全地更新UI以响应您的后台作业(即,如果您想要更新UI,您仍然需要将另一个可运行的返回到UI线程)

原始线程不会锁定UI,因为它们独立于UI线程运行,但您不能在它们上触摸UI组件。这意味着您必须在UI线程上执行要更新UI的任何代码,这意味着需要编写更多代码才能让UI线程运行它。这可能非常复杂。由于使用原始线程的复杂性,应该真正避免使用它们

最常见的后台任务示例是等待服务器的响应。大多数库都会阻塞,直到服务器发送响应,这意味着您无法在UI线程上调用它们,否则,在服务器返回调用之前,您的用户将被阻止执行任何操作。它们不仅会被阻止,而且UI无法更新自身以显示微调器或以其他方式看起来是活动的。这是最好的推到一个背景线程。从技术上讲,处理程序和线程可以做到这一点,但必须专门构造处理程序,以便使用真正的后台线程

这就是AsyncTask胜过处理程序的地方,因为它同时执行真正的后台作业和UI更新。它有一个用于在后台执行一些长时间运行的操作的部分,还有一个用于在完成操作时从UI线程更新UI的部分。它甚至有一个可选的进度部分,因此您可以在任务运行时向UI提供任何中间进度。异步任务的缺点是它们必须有一个结束。继续运行以定期检查是否发生了某些事情、睡眠和检查更多情况的后台作业对AsyncTask模型不利。然而,这并不是说您不能使用处理程序定期启动AsyncTask,只是为了讨论的完整性,我提到了这一点


最后,使用原始线程并不是那么容易,甚至“更好”,因为处理程序几乎可以用更少的代码完成线程可以完成的任何事情。但是,处理程序很难确定Runnable在哪个线程上执行。通常是UI线程,从技术上讲,将其设置为使用非UI线程是很棘手的。这两个选项都存在UI更新问题,因为在真正的后台作业结束时,您必须进行额外的工作才能运行UI作业。AsyncTask确实是我做后台工作的首选方法。

如果您处理线程,我建议您将处理程序与它一起使用:

 Handler handle = new Handler();
 Thread new Thread() 
 {
   @Override
   public void run() 
   {
     try
     {  
        handle.postDelayed(new Runnable() 
        {   
           @Override
           public void run() 
           {        
             "your code goes here"
           }
         },delay);
}
      catch(Exception e)
      {
         e.printStackTrace();
      }
    };
  }
这样你就可以延迟e