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

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

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

【问题讨论】:

    标签: java multithreading main


    【解决方案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 的回答,我建议以下两种方法:

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

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

    【讨论】:

    • 谢谢,这似乎是一个合理的解决方案。
    猜你喜欢
    • 1970-01-01
    • 2016-01-09
    • 1970-01-01
    • 2021-11-07
    相关资源
    最近更新 更多