【问题标题】:How to check if current thread is not main thread如何检查当前线程是否不是主线程
【发布时间】:2012-07-09 19:03:40
【问题描述】:

我需要检查运行某段代码的线程是否是主(UI)线程。我怎样才能做到这一点?

【问题讨论】:

标签: java android multithreading


【解决方案1】:
Looper.myLooper() == Looper.getMainLooper()

如果返回 true,那么你就在 UI 线程上!

【讨论】:

    【解决方案2】:

    您可以使用下面的代码来了解当前线程是否是 UI/主线程

    if(Looper.myLooper() == Looper.getMainLooper()) {
       // Current Thread is Main Thread.
    }
    

    或者你也可以使用这个

    if(Looper.getMainLooper().getThread() == Thread.currentThread()) {
       // Current Thread is Main Thread.
    }
    

    Here is similar question

    【讨论】:

    • 是否应该将后者视为更安全的选择,因为无法保证任意线程都与 Looper 相关联(假设主线程始终与 Looper 相关联)?
    • Looper.myLooper() 如果线程没有与 Looper 关联,将返回 null。所以两者都是安全的并且具有相同的结果,但是第一个在 map 内部搜索以找出 looper 及其相关线程并做一些其他事情时会慢一些。
    【解决方案3】:

    您可以在 android ddms logcat 中验证它,其中进程 ID 相同但线程 ID 不同。

    【讨论】:

      【解决方案4】:

      最好的方法是最清晰、最健壮的方法:*

      Thread.currentThread().equals( Looper.getMainLooper().getThread() )
      

      或者,如果运行时平台是 API 级别 23 (Marshmallow 6.0) 或更高:

      Looper.getMainLooper().isCurrentThread()
      

      请参阅Looper API。请注意,调用Looper.getMainLooper() 涉及同步(请参阅source)。您可能希望通过存储返回值并重用它来避免开销。

         * 感谢 greg7gkb 和 2cupsOfTech

      【讨论】:

      • “在 API 23 或更高版本下”是什么意思?这对我来说没有多大意义..下面的 AAnkit 也发布了完全相同的答案..
      • @Mike 谢谢,我修复了 API 位。 AAnkit 实际上偏爱Looper.myLooper() == Looper.getMainLooper(),我认为这不太清楚。我相信 greg7gkb。
      • 这应该与 == 或 equals() 进行比较,因为 Android Studio 会发出警告吗?
      • @2cupsOfTech 第二个想法,这是个好建议。目前这两个测试在运行时是相同的,因为Thread 不会覆盖equals,因此会退回到==,但将来可能会改变。所以我更正了答案。
      【解决方案5】:

      你可以试试 Thread.currentThread().isDaemon()

      【讨论】:

      • 我不确定 UI 线程是一个守护进程,但我会相信你。但是,您将如何使用我可以(但不应该)创建的守护线程来发挥作用。
      • 我在我的网络应用程序中测试过,它表明 UI 线程是一个守护线程。我在eclipse环境中放了一些调试断点,并进行了验证。线程详细信息显示为 Thread[http-bio-8080-exec-7,5,main]。点击一些 UI 页面并检查调试点。
      • 此外,即使在线程名称详细信息中它显示为“主”,但在线程对象上调用 setDaemon(true) 也会使其成为守护进程。
      • 你没有读到好的部分......我并没有(完全)怀疑它是一个守护进程,我告诉你不能与其他守护进程线程如这个。
      • 换一种说法:一个主线程可能是一个守护线程,但并不是所有的守护线程都是主线程。 (识别主线程是这里所要求的。)
      【解决方案6】:

      总结解决方案,我认为这是最好的:

      boolean isUiThread = VERSION.SDK_INT >= VERSION_CODES.M 
          ? Looper.getMainLooper().isCurrentThread()
          : Thread.currentThread() == Looper.getMainLooper().getThread();
      

      而且,如果你想在 UI 线程上运行一些东西,你可以使用这个:

      new Handler(Looper.getMainLooper()).post(new Runnable() {
          @Override
          public void run() {
             //this runs on the UI thread
          }
      });
      

      【讨论】:

      • Handler 的其他答案建议使用“.postDelayed()”而不是“.post()”。主要区别是什么?您能说说为什么推荐使用“.post()”吗?
      • @AJW 当然,这里是文档:developer.android.com/reference/android/os/…developer.android.com/reference/android/os/…。如果您希望 runnable 从现在开始至少运行 X 毫秒,请使用 postDelayed。
      • 太好了,我很欣赏这些信息。
      • @AJW 错字。意为“从”。我想你知道。 :)
      • @androiddeveloper 我怎样才能运行不在主线程中的东西???
      【解决方案7】:

      您可以查看

      if(Looper.myLooper() == Looper.getMainLooper()) {
         // You are on mainThread 
      }else{
      // you are on non-ui thread
      }
      

      【讨论】:

        【解决方案8】:

        Xamarin.Android 端口:(C#)

        public bool IsMainThread => Build.VERSION.SdkInt >= BuildVersionCodes.M
            ? Looper.MainLooper.IsCurrentThread
            : Looper.MyLooper() == Looper.MainLooper;
        

        用法:

        if (IsMainThread) {
            // you are on UI/Main thread
        }
        

        【讨论】:

          【解决方案9】:

          请允许我在此开头: 我承认这篇文章有“Android”标签,但是,我的搜索与“Android”无关,这是我的最佳结果。为此,对于非 Android SO Java 用户登陆这里,不要忘记:

          public static void main(String[] args{
              Thread.currentThread().setName("SomeNameIChoose");
              /*...the rest of main...*/
          }
          

          在你的代码的其他地方设置这个之后,你可以很容易地检查你是否要在主线程上执行:

          if(Thread.currentThread().getName().equals("SomeNameIChoose"))
          {
              //do something on main thread
          }
          

          在想起这个之前我搜索了一下有点尴尬,但希望它可以帮助其他人!

          【讨论】:

            【解决方案10】:

            简单的 Toast 消息也可以作为快速检查。

            【讨论】:

            • 怎么样??你能显示一下 Toast 代码吗
            • Toast.makeText(activity, "Hello main thread", Toast.LENGTH_LONG).show();
            【解决方案11】:

            首先检查是否是主线程

            在科特林中

            fun isRunningOnMainThread(): Boolean {
                return Thread.currentThread() == Looper.getMainLooper().thread
            }
            

            在 Java 中

            static boolean isRunningOnMainThread() {
              return Thread.currentThread().equals(Looper.getMainLooper().getThread());
            }
            

            【讨论】:

              猜你喜欢
              • 2011-04-02
              • 1970-01-01
              • 1970-01-01
              • 2018-03-21
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多