这个线程能不能存活以及如何使用java.lang.Thread.join()方法

Can this thread be alive and how to use java.lang.Thread.join() method

我之前阅读过一些 SO 问题和文档,但没有找到我的回复:

所以...

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() 时发生了什么

有关信息,我正在使用:

阅读您的一些回复后更新

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

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");
      }
    }
  }
}

两个回复对我帮助很大: and

isAlive() 的文档说:

A thread is alive if it has been started and has not yet died.

join() 的文档说:

Waits at most millis milliseconds for this thread to die

所以,在 join() 之后 returns,

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

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

Waits at most millis milliseconds for this thread to die.

它还会继续

This implementation uses a loop of this.wait calls conditioned on this.isAlive.

并且Thread.isAlive说:

A thread is alive if it has been started and has not yet died.

所以你的代码:

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

所以回答你的问题

It seems it can not be but could one of the t1 be alive ?

对于t1没有,只要你等待的时间超过运行。对于t2.

你的t1.isAlive()永远是假的。您正在执行的线程需要 运行 毫秒。您正在调用 t1.join(5000),它会在该线程死亡后 将该线程与当前线程连接起来 。因为它总是 运行s 快于 5 秒,所以当它到达你检查它是否还活着时它总是死了。

你的t2.isAlive()永远是真的。在 t2 线程上,您在调用 start 方法之前在构造函数中调用 join 。由于线程始终处于死状态,直到调用构造函数中的 start 方法 returns 立即加入。然后允许调用 start 。即使在线程上调用 start 也不意味着它会立即执行。它只是将其标记为可执行,线程调度程序将在将来的某个时间启动它。由于您在构造函数之后立即调用 t2.isAlive(),因此它将始终为真,因为当前线程还不会被换出。

使用您的代码,t1 个线程肯定会始终打印 "I'm not alive",以及 t2、"I'm alive"。

对于 t2 线程,在启动线程之前调用 this.join(...) 很奇怪,因为(作为对@JB 指出的内容的补充),join() doc

This implementation uses a loop of this.wait calls conditioned on this.isAlive.

并且,由于线程尚未启动,连接没有效果,returns立即。

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