如何检查当前线程是否不是主线程


Answers:



122

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

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

或者你也可以使用这个

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

这是类似的问题


8
应该不能将后者视为更安全的选择,因为不能保证有任意线程与Looper关联(假设主线程始终与Looper关联)?
Janus Varmarken

Looper.myLooper()如果线程未与Looper关联,则将返回null。因此两者都是安全的,并具有相同的结果,但第一个则稍慢一些,因为它在地图内查找循环器及其相关线程并做其他事情。
Saeed Masoumi

59

最好的方法是最清晰,最可靠的方法:*

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

或者,如果运行时平台是API级别23(棉花糖6.0)或更高版本:

Looper.getMainLooper().isCurrentThread()

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

   * 信用greg7gkb2cupsOfTech


“在API 23或更高版本下”是什么意思?这对我来说没有多大意义。.同样的答案也由下面的AAnkit发布。-–
Mike

@Mike谢谢,我修复了API位。AAnkit实际上赞成Looper.myLooper() == Looper.getMainLooper(),我认为这还不太清楚。我相信greg7gkb。
Michael Allan

1
这是否应该与==或equals()进行比较,因为Android Studio会发出警告?
2cupsOfTech

@ 2cupsOfTech关于第二个想法,这是个好建议。当前,这两个测试在运行时是相同的,因为Thread不会覆盖equals,因此会回落到==,但是将来可能会改变。所以我纠正了答案。
迈克尔·艾伦

25

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

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
    }
});


2

请允许我在此开头:我承认该帖子带有“ 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
}

在记忆之前,我曾进行过一些尴尬的搜索,但希望它会对其他人有所帮助!


1

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


1

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
}

-6

您可以尝试Thread.currentThread()。isDaemon()


我不确定UI线程是否是守护进程,但是我会相信您的。但是,您将如何利用我可以(但不应)创建的守护进程线程来有所作为。
AxelH '16

我在Web应用程序中进行了测试,它表明UI线程是一个Daemon线程。我在Eclipse环境中放置了一些调试断点并进行了验证。线程详细信息显示为Thread [http-bio-8080-exec-7,5,main]。单击一些UI页面,然后检查调试点。
Shailendra Singh

同样,即使线程名称中的详细信息显示为“ main”,但在线程对象上调用setDaemon(true)也会使其成为守护程序。
Shailendra Singh

您没有阅读其中的好内容……我并没有完全怀疑它是否是Daemon,我是在告诉您您无法与其他Daemon线程有所区别。
AxelH

换句话说,主线程可能是守护线程,但并非所有守护线程都是主线程。(确定主线程是这里要问的问题。)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.