我以前读过一些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
如果线程已启动但尚未终止,则它是活动的。
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可以是活动的"。