这个线程能活着吗?以及如何使用java.lang.thread.join()方法



我以前读过一些SO问题和文档,但没有找到我的答案:

  • 一个线程在java中能存活多久
  • Java线程何时处于活动状态
  • http://journals.ecs.soton.ac.uk/java/tutorial/java/threads/states.html

所以。。。

public class MyThread extends Thread {
public MyThread() {
this.setName("MyThread-" + System.currentTimeMillis());
this.start();
}
public MyThread(long millis) throws InterruptedException {
this.setName("MyThread-" + System.currentTimeMillis());
this.join(millis);
this.start();
}
@Override
public void run() {
System.out.println("I am running...");
// This thread does not sleep... no Thread.sleep() in run method.
// Do some things like requesting a database
// Database response happens in less time that the timeout
}
}
public class MyClass {
public MyClass(){
for (int i = 0; i < 5; i++) {
Thread t1 = new MyThread();
t1.join(5000);
if (t1.isAlive()) {
System.out.println("I'm alive");
// do some things
} else {
System.out.println("I'm not alive");
}
Thread t2 = new MyThread(5000);
if (t2.isAlive()) {
System.out.println("I'm alive");
// do some things
} else {
System.out.println("I'm not alive");
}
}
}
}

似乎不可能,但其中一个t1还活着吗?t2呢?当我在start()之后呼叫join()时发生了什么

有关信息,我使用:

  • JVM:Java HotSpot(TM)客户端虚拟机(20.45-b01,混合模式,共享)
  • Java:版本1.6.0_45,供应商Sun Microsystems股份有限公司

阅读部分回复后更新

如果我理解的话,更好的实现方式应该是:

public class MyThread extends Thread {
public MyThread() {
super("MyThread-" + System.currentTimeMillis());
}
@Override
public void run() {
System.out.println("I am running...");
// This thread does not sleep... no Thread.sleep() in run method.
// Do some things like requesting a database
// Database response happens in less time that the timeout
}
}
public class MyClass {
public MyClass(){
for (int i = 0; i < 5; i++) {
Thread t1 = new MyThread();
t1.start();
t1.join(5000);
if (t1.isAlive()) {
System.out.println("I'm alive");
// do some things
} else {
System.out.println("I'm not alive");
}
}
}
}

这两种回答对我帮助很大:https://stackoverflow.com/a/29775219/1312547和https://stackoverflow.com/a/29775083/1312547

isAlive()的文档说明:

如果线程已启动但尚未终止,则它是活动的。

join()的文档说:

等待此线程终止的时间最多为毫秒

因此,在join()返回后,

  • 要么线程已经死亡,isAlive()将为false
  • 或者线程还没有死,但延迟已经过去,isAlive()可能为true。这是可能的,但极不可能,因为线程有5秒钟的时间来完成打印到控制台的简单工作

注意,尽管Thread.join(long)的(JDK 7)文档中说

等待此线程死亡的时间最多为millis毫秒。

它还继续使用

此实现使用以this.isAlive为条件的this.wait调用循环。

Thread.isAlive说:

如果线程已启动但尚未终止,则它是活动的。

因此,使用您的代码:

  • 调用t1.isAlive()时,它始终是false,因为您是在启动线程(从构造函数)后加入的
  • 当调用t2.isAlive()时,大部分时间都是true,因为
    • 在启动线程(在构造函数中)之前加入,立即返回
    • 线程刚刚启动(在构造函数中)

所以要回答您的问题

似乎不可能,但其中一个t1还活着吗?

对于t1,只要您等待的时间超过运行所需的时间。对于t2

您的t1.isAlive()将始终为false。您正在执行的线程需要一毫秒才能运行。您正在调用t1.join(5000),一旦该线程死亡,它就会将其与当前线程连接起来。由于它总是跑得快于5秒,那么当它到达你的检查它是否活着时,它总是死了。

你的t2.isAlive()永远是真实的。在t2线程上,在调用start方法之前,您将在构造函数中调用join。由于在调用start方法之前线程总是死的,因此构造函数中的联接会立即返回。这样就可以调用start。即使在线程上调用了start,也不意味着它立即执行。它只是将其标记为可供执行,线程调度程序将在将来的某个时刻启动它。由于您在构造函数之后立即调用t2.isAlive(),因此它将始终为true,因为当前线程尚未交换出去。

使用您的代码,t1线程肯定会始终打印"I’m not alive",而t2则打印"I‘m alive"。

对于t2线程,在启动线程之前调用this.join(...)是很奇怪的,因为(作为@JB所指出的补充),join()文档说

此实现使用This.wait调用的循环,该调用以This.isAlive.为条件

而且,由于线程还没有启动,所以联接没有效果,并立即返回。

但你的问题是什么能让t1活着。只需在run()方法中添加一个Thread.sleep(6000),就会看到线程处于活动状态。这意味着,如果线程完成的任务(DB请求,…)比join()中设置的超时时间长,那么答案是"是的,t1可以是活动的"。

最新更新