Java Handler、Runnable 和 Threads 之间有什么区别?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21194762/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 07:14:02  来源:igfitidea点击:

What is the different between Handler, Runnable, and Threads?

javaandroidmultithreadingandroid-asynctaskthread-safety

提问by Hong Wei Wang

What is the difference between Handler, Runnable, and Threads?

Handler、Runnable 和 Threads 之间有什么区别?

While I was working with android, and I need something to run in the background. I use Threads to run it. Usually I would write a class that extends Thread and implement the run method.

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

I have also saw some examples that implments runnable and pass into runnable into Threads.

我还看到了一些实现 runnable 并将 runnable 传递到线程的示例。

However I am still confused. Can someone give me a clear explanation?

然而我仍然很困惑。有人可以给我一个明确的解释吗?

  1. What is the point of Runnable if one can write the background code in the Thread's run method?
  2. How is Handler used inside thread and why do we need to use it.
  3. Android has another thing call runOnUiThread, How do we use that? I know that it is used for updating the UI.
  1. 如果可以在 Thread 的 run 方法中编写后台代码,那么 Runnable 的意义何在?
  2. Handler 是如何在线程内部使用的,为什么我们需要使用它。
  3. Android 还有一个叫做 runOnUiThread 的东西,我们如何使用它?我知道它用于更新用户界面。

回答by Ankur Shanbhag

What is the point of Runnable if one can write the background code in the Thread's run method?

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

Runnableis an interface which used for creating a new thread class similar to the thread class created by extending java.lang.Threadclass. Only difference is, Runnableinterface allows the class to extend other class (if required) to override/inherit functionality of some class. Extending java.lang.Threadclass will revoke this capability.

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

Also, Runnable interface represent a Task which can be executed by either plain Thread or Executors or any other means. so logical separation of Task as Runnable than Thread is good design decision.

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

Read more: http://javarevisited.blogspot.com/2012/01/difference-thread-vs-runnable-interface.html#ixzz2qgjDYJhT

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

回答by William Morrison

Why use Runnable over Thread?

为什么使用 Runnable over Thread?

  • Runnableseparates code that needs to run asynchronously, from howthe code is run. This keeps your code flexible. For instance, asynchronous code in a runnable can run on a threadpool, or a dedicated thread.

    A Threadhas state your runnable probably doesn't need access to. Having access to more state than necessary is poor design.

    Threads occupy a lot of memory. Creating a new thread for every small actions takes processing time to allocate and deallocate this memory.

  • Runnable中隔离代码,需要异步运行,从如何运行代码。这使您的代码保持灵活。例如,可运行对象中的异步代码可以在线程池或专用线程上运行。

    AThread具有您的可运行对象可能不需要访问的状态。访问比必要更多的状态是糟糕的设计。

    线程占用大量内存。为每个小动作创建一个新线程需要处理时间来分配和释放此内存。

What is runOnUiThread actually doing?

runOnUiThread 实际上在做什么?

  • Android's runOnUiThreadqueues a Runnableto execute on the UI thread. This is important because you should never update UI from multiple threads. runOnUiThreaduses a Handler.

    Be aware if the UI thread's queue is full, or the items needing execution are lengthy, it may be some time before your queued Runnableactually runs.

  • Android 的runOnUiThread 将 a排队Runnable以在 UI 线程上执行。这很重要,因为您永远不应该从多个线程更新 UI。 runOnUiThread使用一个Handler.

    请注意,如果 UI 线程的队列已满,或者需要执行的项目很长,则可能需要一段时间才能Runnable真正运行排队。

What is a Handler?

什么是处理程序?

  • A handler allows you to post runnables to execute on a specific thread. Behind the scenes, runOnUi Thread queues your Runnableup with Android's Ui Handler so your runnable can execute safely on the UI thread.
  • 处理程序允许您发布可运行对象以在特定线程上执行。在幕后,runOnUi Thread 将您Runnable与 Android 的 Ui 处理程序进行排队,以便您的可运行对象可以在 UI 线程上安全地执行。

回答by marcinj

Handler, Runnable, and Threads actually work together, I dont think you should compare them.

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

Handler

处理程序

allows send messages between two threads in a safe manner, that means that sending thread puts message into destination thread queue, and this destination queue will process this message in its appropriate time.

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

Runnable

可运行

this is an interface that you implement, in implementation you put logic you want to execute on some thread. You can actually use Runnable also in non thread related places. Lots of Java apis actually use Runnable, not only Thread's. You can post Runnable using handler, or you can use it with executors. Runnables are nice because you can implement them in a form of anonymous implementation.

这是您实现的接口,在实现中,您将要在某个线程上执行的逻辑放入。您实际上也可以在与线程无关的地方使用 Runnable。许多 Java api 实际上使用 Runnable,而不仅仅是 Thread 的。您可以使用处理程序发布 Runnable,也可以将其与执行程序一起使用。Runnable 很好,因为您可以以匿名实现的形式实现它们。

UniThread

单线程

you meant UI Thread? Most user interfaces implements its workings in single thread, all UI elements: windows/widgets communicate using messages (just like in Handler). Ie. user presses button, this initiates a message with information that button was pressed, it is send to UI thread and finally delivered to your listener.

你的意思是 UI 线程?大多数用户界面在单线程中实现其工作,所有 UI 元素:窗口/小部件使用消息进行通信(就像在 Handler 中一样)。IE。用户按下按钮,这将启动一条带有按钮被按下信息的消息,它被发送到 UI 线程并最终传递给您的侦听器。

In Android it is forbidden (results in exception) to modify UI elements from non UI thread, this makes sense - if you would modify it from other thread this could happen while UI thread is doing some changes to the same widget - resulting in Undefined Behaviour.

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

回答by Prem

1. Why runnable ?

1. 为什么是可运行的?

Runnable is just an interface you need to instantiate a thread to contain it. Whereas thread already contains the ability to spawn a thread.If you extend Thread you can't extend anything else (Java doesn't support multiple inheritance). You can have multiple interfaces on a class, therefore you could have Runnable.

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

Also, When you extends Thread class, each of your thread creates unique object and associate with it. When you implements Runnable, it shares the same object to multiple threads.

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

2. Why to Use handler and what is it ?

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

Handler is written in Java (internally use a Thread), so everything you can do with Handler, you can achieve using a Thread too.

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

So why should you use Handler? Reason is as below

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

  • Handler allows you to send and process Message and Runnable objects associated with a thread's MessageQueue. To put it in simple terms, handler makes your job easy.

  • Android has two main rules for handling threads:

  • Do not block the UI thread

  • Do not access the Android UI toolkit from outside the UI thread
  • Handler 允许您发送和处理与线程的 MessageQueue 关联的 Message 和 Runnable 对象。简单来说,handler 让你的工作变得轻松。

  • Android 有两个处理线程的主要规则:

  • 不要阻塞 UI 线程

  • 不要从 UI 线程之外访问 Android UI 工具包

To bind by the 2 rules stated above, In android we have 3 built-in methods that can handle the situation when one of your Activity classes are run on or called from a different thread.

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

We can then schedule the UI updates to be run on the UI thread with these three methods below. The Activity or View then works as a handler (more on handlers below) and schedules your runnable to the UI thread:

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

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

3. What is UI Thread ?

3.什么是UI线程?

UI thread is the main thread in which the UI elements like View and Activity are rendered. Any time consuming operations should not happen in the UI Thread. The application default runs in UI Thread. You need not do anything special to use the UI Thread.

UI 线程是主线程,其中渲染 View 和 Activity 等 UI 元素。任何耗时的操作都不应该发生在 UI 线程中。应用程序默认在 UI 线程中运行。您无需执行任何特殊操作即可使用 UI 线程。

回答by Ravindra babu

I use Threads to run it. Usually I would write a class that extends Thread and implement the run method.

1.What is the point of Runnable if one can write the background code in the Thread's run method?

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

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

Using Runnable and creating a Thread from Runnable is general practice.

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

From oracle tutorial on concurrencyregarding RunnableVs Threadusage :

来自关于Vs用法并发的oracle 教程:RunnableThread

Runnable object, is more general, because the Runnable object can subclass a class other than Thread.

Runnable 对象,比较通用,因为 Runnable 对象可以子类化 Thread 以外的类。

2.How is Handler used inside thread and why do we need to use it.

2.Handler在线程内部是如何使用的,为什么要使用它。

It's a vast topic to explain. In simpler terms from official documentation site:

这是一个需要解释的广泛话题。来自官方文档站点的简单术语:

  1. Handlerallows you to send and process Messageand Runnableobjects associated with a thread's MessageQueue. Each Handlerinstance is associated with a single thread and that thread's message queue.

  2. When you create a new Handler, it is bound to the thread / message queue of the thread that is creating it -- from that point on, it will deliver messages and runnables to that message queue and execute them as they come out of the message queue.

  3. There are two main uses for a Handler: (1) to schedule messages and runnables to be executed as some point in the future; and (2) to enqueue an action to be performed on a different thread than your own

  4. When a process is created for your application, its main thread is dedicated to running a message queue that takes care of managing the top-level application objects (activities, broadcast receivers, etc) and any windows they create. You can create your own threads, and communicate back with the main application thread through a Handler.This is done by calling the same post or sendMessagemethods as before, but from your new thread. The given Runnableor Message will then be scheduled in the Handler's message queue and processed when appropriate.

  1. 处理程序允许您发送和处理MessageRunnable线程的MessageQueue. 每个Handler实例都与一个线程和该线程的消息队列相关联。

  2. 当你创建一个 new 时Handler,它被绑定到创建它的线程的线程/消息队列——从那时起,它将把消息和可运行对象传递到该消息队列,并在它们从消息队列中出来时执行它们.

  3. a 有两个主要用途Handler:(1) 安排消息和可运行对象在将来的某个时间点执行;(2) 将要在与您自己的线程不同的线程上执行的操作排入队列

  4. 当为您的应用程序创建进程时,其主线程专用于运行消息队列,该队列负责管理顶级应用程序对象(活动、广播接收器等)及其创建的任何窗口。您可以创建自己的线程,并通过 Handler 与主应用程序线程进行通信。这是通过调用与sendMessage以前相同的帖子或方法来完成的,但来自您的新线程。Runnable然后将在处理程序的消息队列中安排给定或消息并在适当时进行处理。

This picture from blog.mindorks.comarticle by Anishar Ali explains concepts clearly.

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

enter image description here

在此处输入图片说明

3.Android has another thing call runOnUiThread, How do we use that? I know that it is used for updating the UI.

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

You can find more details by looking into implementation of runOnUiThread

您可以通过查看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();
        }
    }

Refer to below post for example code of Handlerusage.

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

Android: Toast in a thread

Android:在线程中吐司

回答by Harshit Joshi

Runnable Interface is parent of Thread Class and run() is method of Runnable Interface So normally we should prefer Runnable interface over extending thread class because we don't want to change behavior of the class and we can also extend another class .It also help in achieving loose coupling as well as we have a benefit of changing the User Interface from any other class.

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

We Can change Ui in 4 ways

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

1.By using Handler example

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.By Using runOnUIThread() we have to attach runOnUIThread with post it can be easily understood with example

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.By using any View we can call by any view here i have called with switch

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.By making Handler in another Thread we have to define Looper because by default it attach us to our thread looper

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

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

This are 4 ways of implementing so I think from it you may now something about runnable thread and runOnUIThread() and Handler is written by other person beautifully.

这是 4 种实现方式,因此我认为您现在可以了解有关可运行线程和 runOnUIThread() 的内容,并且 Handler 是由其他人编写的精美的。