Handler,Runnable和Threads有什么不同?

问题描述 投票:29回答:6

Handler,Runnable和Threads有什么区别?

当我使用android时,我需要在后台运行一些东西。我使用Threads来运行它。通常我会编写一个扩展Thread的类并实现run方法。

我还看到了一些实现runnable并将runnable传递给Threads的例子。

不过我还是很困惑。有人能给我一个明确的解释吗?

  1. 如果可以在Thread的run方法中编写后台代码,那么Runnable有什么意义呢?
  2. Handler如何在内部线程中使用,为什么我们需要使用它。
  3. Android有另外一个调用runOnUiThread的东西,我们如何使用它?我知道它用于更新UI。
java android multithreading android-asynctask thread-safety
6个回答
23
投票

为什么在线程上使用Runnable?

  • Runnable根据代码的运行方式分离需要异步运行的代码。这使您的代码保持灵活性。例如,runnable中的异步代码可以在线程池或专用线程上运行。 Thread表示你的runnable可能不需要访问。获得更多不必要的状态是糟糕的设计。 线程占用了大量内存。为每个小动作创建一个新线程需要处理时间来分配和释放这个内存。

runOnUiThread究竟在做什么?

  • Android的runOnUiThread将一个Runnable排队,以便在UI线程上执行。这很重要,因为您永远不应该从多个线程更新UI。 runOnUiThread使用Handler。 请注意,如果UI线程的队列已满,或者需要执行的项目很长,那么在排队的Runnable实际运行之前可能需要一段时间。

什么是处理程序?

  • 处理程序允许您发布runnables以在特定线程上执行。在幕后,runOnUi Thread使用Android的Ui Handler将你的Runnable排队,这样你的runnable就可以在UI线程上安全地执行。

10
投票

1.为什么要跑?

Runnable只是一个实例化线程以包含它的接口。而线程已经包含了生成线程的能力。如果扩展Thread,则不能扩展其他任何东西(Java不支持多重继承)。您可以在类上拥有多个接口,因此您可以拥有Runnable。

此外,当您扩展Thread类时,每个线程都会创建唯一对象并与之关联。实现Runnable时,它将同一对象共享给多个线程。

2.为什么要使用处理程序,它是什么?

Handler是用Java编写的(内部使用Thread),所以你可以用Handler做的一切,你也可以使用Thread实现。

那么为什么要使用Handler?原因如下

  • Handler允许您发送和处理与线程的MessageQueue关联的Message和Runnable对象。简而言之,处理程序使您的工作变得轻松。
  • Android有两个处理线程的主要规则:
  • 不要阻止UI线程
  • 不要从UI线程外部访问Android UI工具包

要通过上面提到的2个规则进行绑定,在android中我们有3个内置方法可以处理当一个Activity类在不同线程上运行或调用时的情况。

然后,我们可以使用以下三种方法安排UI更新在UI线程上运行。然后,Activity或View作为处理程序(下面的处理程序更多)并将runnable安排到UI线程:

  1. Activity.runOnUiThread(可运行) View.post(可运行) View.postDelayed(Runnable,long)//(long =调度时间)

3.什么是UI线程?

UI线程是呈现View和Activity等UI元素的主线程。任何耗时的操作都不应该在UI线程中发生。应用程序默认值在UI Thread中运行。您不需要做任何特殊的事情来使用UI线程。


4
投票

Handler,Runnable和Threads实际上是一起工作的,我不认为你应该比较它们。

处理器

允许以安全的方式在两个线程之间发送消息,这意味着发送线程将消息放入目标线程队列,并且此目标队列将在适当的时间处理此消息。

可运行

这是一个你实现的接口,在实现中你将逻辑放在某个线程上。实际上,您也可以在非线程相关的位置使用Runnable。很多Java apis实际上都使用Runnable,而不仅仅是Thread。您可以使用处理程序发布Runnable,也可以将其与执行程序一起使用。 Runnables很不错,因为您可以以匿名实现的形式实现它们。

UniThread

你的意思是UI线程?大多数用户界面在单线程中实现其工作,所有UI元素:windows / widgets使用消息进行通信(就像在Handler中一样)。 IE浏览器。用户按下按钮,这将启动一条消息,其中包含按下按钮的信息,它将发送到UI线程,最后传送给您的监听器。

在Android中,禁止(导致例外)从非UI线程修改UI元素,这是有道理的 - 如果你要从其他线程修改它,这可能发生在UI线程对同一个小部件进行一些更改时 - 导致未定义的行为。


1
投票

我使用Threads来运行它。通常我会编写一个扩展Thread的类并实现run方法。

1.如果可以在Thread的run方法中编写后台代码,Runnable有什么意义?

使用Runnable并从Runnable创建一个Thread是一般做法。

来自concurrency的oracle教程关于RunnableThread的用法:

Runnable对象更通用,因为Runnable对象可以继承Thread以外的类。

2.如何在内部线程中使用Handler,为什么我们需要使用它。

这是一个很难解释的话题。从官方文档站点简单来说:

  1. Handler允许您发送和处理与线程的Message相关联的RunnableMessageQueue对象。每个Handler实例都与一个线程和该线程的消息队列相关联。
  2. 当你创建一个新的Handler时,它被绑定到创建它的线程的线程/消息队列 - 从那时起,它将消息和runnables传递给该消息队列并在消息出来时执行它们队列。
  3. Handler有两个主要用途:(1)安排消息和runnables作为未来某些点执行; (2)将要在不同于自己的线程上执行的操作排入队列
  4. 为应用程序创建进程时,其主线程专用于运行消息队列,该队列负责管理顶级应用程序对象(活动,广播接收器等)及其创建的任何窗口。您可以创建自己的线程,并通过Handler与主应用程序线程进行通信。这是通过调用与以前相同的post或sendMessage方法完成的,但是来自你的新线程。然后,将在Handler的消息队列中调度给定的Runnable或Message,并在适当时进行处理。

来自Anishar Ali的blog.mindorks.com文章的这张照片清楚地解释了概念。

enter image description here

3.Android还有另一个叫runOnUiThread的东西,我们怎么用呢?我知道它用于更新UI。

您可以通过查看runOnUiThread的实现来查找更多详细信息

/**
     * Runs the specified action on the UI thread. If the current thread is the UI
     * thread, then the action is executed immediately. If the current thread is
     * not the UI thread, the action is posted to the event queue of the UI thread.
     *
     * @param action the action to run on the UI thread
     */
    public final void runOnUiThread(Runnable action) {
        if (Thread.currentThread() != mUiThread) {
            mHandler.post(action);
        } else {
            action.run();
        }
    }

有关Handler用法的示例代码,请参阅下面的帖子。

Android: Toast in a thread


0
投票

如果可以在Thread的run方法中编写后台代码,那么Runnable有什么意义呢?

Runnable是一个接口,用于创建一个类似于通过扩展java.lang.Thread类创建的线程类的新线程类。唯一的区别是,Runnable接口允许类扩展其他类(如果需要)来覆盖/继承某些类的功能。扩展java.lang.Thread类将撤销此功能。

此外,Runnable接口表示可以由普通线程或执行器或任何其他方式执行的任务。所以将Task作为Runnable与Thread进行逻辑分离是一个很好的设计决策。

阅读更多:http://javarevisited.blogspot.com/2012/01/difference-thread-vs-runnable-interface.html#ixzz2qgjDYJhT


0
投票

Runnable Interface是Thread Class的父级,run()是Runnable Interface的方法所以通常我们应该优先选择Runnable接口而不是扩展线程类,因为我们不想改变类的行为,我们也可以扩展另一个类。它也有帮助实现松散耦合以及我们从任何其他类更改用户界面的好处。

我们可以通过4种方式改变Ui

1.使用Handler示例

public class MainActivity extends AppCompatActivity {    
private Handler mainHandler=new Handler();
class ExampleRunnable implements Runnable {
        int seconds;

        public ExampleRunnable(int seconds) {
            this.seconds = seconds;
        }

        @Override
        public void run() {
            for (int i = 0; i < seconds; i++) {
 mainHandler.post(new Runnable() {
                        @Override
                        public void run() {
                        button.setText("50% process completed");
                        }
                    });

2.通过使用runOnUIThread(),我们必须将runOnUIThread附加到post上,可以通过示例轻松理解

class ExampleRunnable implements Runnable {
        int seconds;



 public ExampleRunnable(int seconds) {
        this.seconds = seconds;
    }

    @Override
    public void run() {runOnUIThread.post(new Runnable() {
                    @Override
                    public void run() {
                        button.setText(" Runnable");
                    }
                });
            }

3.使用任何视图,我们可以通过任何视图调用此处,我已使用开关调用

public class MainActivity extends AppCompatActivity {
 private Switch aSwitch;
@Override
    protected void onCreate(Bundle savedInstanceState) {
 aSwitch=findViewById(R.id.switch1);
class ExampleRunnable implements Runnable {
            int seconds;



     public ExampleRunnable(int seconds) {
            this.seconds = seconds;
        }

        @Override
        public void run() { aSwitch.post(new Runnable() {
                        @Override
                        public void run() {
                            button.setText(" Runnable");
                        }
                    });
                }

4.通过在另一个Thread中创建Handler,我们必须定义Looper,因为默认情况下它将我们附加到我们的线程循环器

Handler threadHandler=new Handler(Looper.getMainLooper());
threadHandler.post(new Runnable()
{
                            @Override
                            public void run() {
                                button.setText(" Runnable");
                            }
                        });
                    }

这是4种实现方式,所以我想你现在可能有关于runnable线程和runOnUIThread()和Handler的内容是由其他人精美编写的。

© www.soinside.com 2019 - 2024. All rights reserved.