Java线程的isAlive()方法无法正常工作?

5

我正在尝试使用Java线程的isAlive()方法示例。但是我发现即使线程已经启动,isAlive()方法仍然返回false。请问有人可以告诉我我做错了什么吗?以下是代码片段。

package app;

public class ThreadAliveDemo {

    public static void main(String[] args) {

        Thread myThread;

        myThread = new Thread()
        {
            public void run()
            {
                            Thread.sleep(3000);
                System.out.println("My Thread.");
            }
        };

        myThread.setName("My Thread");
        myThread.start();

        if(!myThread.isAlive())
        {
            myThread.setName("My Thread");
            myThread.start();
        }

    }

}

1
请使用Thread.getState()代替,它提供了额外的信息。同时,启动两次线程也没有任何效果。 - bestsss
关于@bestsss的建议:Brian Goetz的书《Java Concurrency in Practice》中说:“Thread.getState的结果不应该用于并发控制,并且在测试方面的有限用处。它的主要作用是作为调试信息的来源。” - WoodenKitty
@WoodenKitty,在线程启动之前,getState() 方法会保持稳定(可能需要与线程启动进行同步)。Goetz 的建议非常可靠,但在这种情况下不适用。 - bestsss
5个回答

12

在调用start()isAlive()之间,线程很有可能已经开始执行并完成了。

Java不保证这些事情发生的顺序。它可能会立即执行生成的线程,也可能会选择稍后执行。

顺带说一下,您的代码试图在线程死亡后重新启动线程。这是不允许的

不允许启动一个已经终止的线程。 特别地,一旦线程已经完成执行, 就不能重新启动它。

因此,在检查isAlive()之后调用start()永远不会起作用。


啊...我需要在我的大脑和手指周围包装一个synchronized块。 - skaffman
1
不,我尝试在run方法内部使用Thread.sleep(3000)调用。但仍然遇到相同的问题。 - Rise
但是为什么?我已经让我的线程睡眠了3秒,然后检查了isAlive()方法的调用。在这种情况下,我认为isAlive()方法应该返回true,但它仍然返回true的结果。 - Rise
@Rupesh:我理解你的意思。但我要告诉你的是,这个程序在根本上有缺陷。你不能用线程进行这种松散的编码,并期望得到有用的结果。 - skaffman
1
我更喜欢原问题中的评论,使用getState()而不是isAlive(),以防线程尚未启动。 - Guy Schalnat
显示剩余4条评论

4

如果我没记错,Java 的线程切换时间相对较长,因此可能是因为线程还启动,导致 isAlive 失败。尝试在 thread.start() 和 thread.isAlive() 之间添加一些等待时间。


我尝试让线程休眠3秒钟,但是仍然遇到了相同的问题。 - Rise
尝试让调用线程休眠一秒钟(并且让子线程休眠三秒钟)。 - user253984
3
我是唯一一个认为这种行为非常无用的人吗? - Simon
1
我更喜欢在getState()的原始问题上使用注释,而不是在检查isAlive()之前添加等待时间。竞态条件从来都不好。 - Guy Schalnat
我在想,是不是线程切换需要很长时间。测试代码块紧随start()调用之后,你几乎不能期望测试会产生可靠的结果。当然,假设线程状态是异步设置的,这似乎是情况。 - orodbhen

1

我还没有在Java中进行过任何多线程编程,但是看起来你的线程在isAlive()检查之前可能已经运行并退出了。毕竟,你的线程似乎只是打印一些东西然后就结束了。


1
最近发生了这样的事情,我使用以下方法解决了它:

if(yourThread.getState() == Thread.State.NEW){    
    yourThread.start();
}

使用yourThread.isAlive()的替代方案;


你的回答其实并没有为之前已经提到的回答和评论做出任何有贡献的补充,而且这些内容是一段时间之前发布的。 - Adrian Mole

0
我不明白你发布的代码有什么意义。Thread.start() 启动线程:你不需要启动两次。我不明白你的代码如何会出现这样一种情况——有一个线程却不知道它是否已经启动了;不管怎样,有很多方法可以编写代码来解决这个问题,使其不可能发生。

1
重点不在于在实际情况中直接使用代码,而在于让概念清晰明了。 - Rise
但这只意味着当start()返回时,线程实际上还没有启动。你知道它是异步的。我不明白所展示的概念是什么。 - user207421

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接