有啥方法可以区分主线程和它产生的任何线程吗?

Posted

技术标签:

【中文标题】有啥方法可以区分主线程和它产生的任何线程吗?【英文标题】:Is there any way to distinguish the main Thread from any Threads that it spawns?有什么方法可以区分主线程和它产生的任何线程吗? 【发布时间】:2012-02-22 04:54:48 【问题描述】:

我知道主线程上的getName()函数会返回字符串main,但这可以用setName()改变。

有什么方法可以始终确定应用程序的主线程吗?

【问题讨论】:

【参考方案1】:

一种可能性是在main() 的开头调用Thread.currentThread(),并保留引用。

【讨论】:

比如说我在写一个框架,我有一个静态方法,我只希望主线程能够执行? 听起来你好像遇到了设计问题 ;-) 如果你必须有这个,我会简单地记录它(就像大多数 GUI 框架记录了你只能从事件调度线程)。 如果你看看 android API。我相信只有主线程/活动可以执行 UI 更改。可以将消息传递回主线程,请求它进行更改,但如果有其他任何尝试,则会引发异常。 @Jivings:如果您的情况类似于 GUI 框架,那么您的问题与您描述的略有不同。您不需要识别主线程,您需要识别执行特定代码的线程(GUI 框架中的消息循环)。 @axtavt 我认为这将是主线程,但也许不是。【参考方案2】:

似乎主线程的 id1,如Thread.getId() 所示:

class test
    public static boolean isMainThread()
        return Thread.currentThread().getId() == 1;
    

    public static void main(String[]args)
        System.out.println(isMainThread());
        new Thread( new Runnable()
            public void run()
                System.out.println(isMainThread());
            
        ).start();
    
    

我不确定它是规范的一部分还是特定于实现的功能。

一种更便携的方式是这样的:

class test

    static long mainThreadId = Thread.currentThread().getId();

    public static boolean isMainThread()
        return Thread.currentThread().getId() == mainThreadId;
    

    public static void main(String[]args)
        System.out.println(isMainThread());
        new Thread( new Runnable()
            public void run()
                System.out.println(isMainThread());
            
        ).start();
    
    

需要注意的是,mainThreadId 必须位于由主线程加载的类中(例如,包含 main 方法的类)。例如,这不起作用:

class AnotherClass
    static long mainThreadId = Thread.currentThread().getId();

    public static boolean isMainThread()
        return Thread.currentThread().getId() == mainThreadId;
    

class test
    public static void main(String[]args)
        //System.out.println(isMainThread());
        new Thread( new Runnable()
            public void run()
                System.out.println(AnotherClass.isMainThread());
            
        ).start();
    
    

【讨论】:

不错的一个。我猜这将是特定于实现的,因为 Thread 存储结构不是由 JVM 规范定义的。 很公平。从好的方面来说,appears 这种行为是java.lang.Thread 源代码的一部分,所以它不是 JVM 内部的。 我不知道这种方法。看起来你的答案是正确的,然后弗拉德!虽然功能可以被实现覆盖,但假设它不会被覆盖是合理的! @Vlad:是什么让您认为 java.lang.Thread 的源代码不是特定于实现的? @Jivings:不,假设未记录的行为在不同的 JavaVM 实现或版本之间不会改变或保持一致是不合理的。【参考方案3】:

根据您的问题和您对 cme​​ts 的回答,我建议以下两种方法:

    将所有请求放到一个事件队列中,主线程将接受 来自请求队列的请求以调用您正在谈论的方法 关于。在这种情况下,必须有任何其他方法的合同 想要访问您正在谈论的方法只能这样做 通过事件队列(与 EDT 相同)。

    在您希望被调用的方法中放置一个额外的参数 main 仅充当令牌。在方法内部检查令牌是否 正确(只有main 会拥有它/知道它)。如果它是正确的,那么 继续。否则返回false。当然如果允许你做这样的修改

【讨论】:

谢谢,这似乎是一个合理的解决方案。

以上是关于有啥方法可以区分主线程和它产生的任何线程吗?的主要内容,如果未能解决你的问题,请参考以下文章

在java层用线程调用native方法 jni能回调主线程的方法吗?

并发编程之线程属性

主线程和子线程的区别

qt中通过重写run方法创建线程与通过movetothread方法有啥区别

从主线程触发一个线程中的动作的防弹方法?

我可以在主线程(UI 线程)之外创建 UI 吗?