简体   繁体   English

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

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

I have read some SO question and docs before but do not find my response : 我以前读过一些SO问题和文档,但没有找到我的答复:

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

    }
  }
}

It seems it can not be but could one of the t1 be alive ? 这似乎也不能,但可以在一个t1活着? What about t2 ? t2怎么样? What happend when I call join() after start() start()之后调用join()时发生的事情

For information, I am using : 有关信息,我正在使用:

  • JVM: Java HotSpot(TM) Client VM (20.45-b01, mixed mode, sharing) JVM:Java HotSpot(TM)客户端VM(20.45-b01,混合模式,共享)
  • Java: version 1.6.0_45, vendor Sun Microsystems Inc. Java:版本1.6.0_45,供应商Sun Microsystems Inc.

Update after reading some of your responses 阅读部分回复后更新

If I understand, a better implementation would be something like : 如果我理解,更好的实现将是这样的:

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

Both responses have helped me a lot : https://stackoverflow.com/a/29775219/1312547 and https://stackoverflow.com/a/29775083/1312547 这两个回复对我帮助很大: https//stackoverflow.com/a/29775219/1312547https://stackoverflow.com/a/29775083/1312547

The documentation of isAlive() says: isAlive()的文档说:

A thread is alive if it has been started and has not yet died. 如果线程已经启动并且尚未死亡,则该线程处于活动状态。

The documentation of join() says: join()的文档说:

Waits at most millis milliseconds for this thread to die 此线程最多等待毫秒毫秒

So, after join() returns, 所以,在join()返回后,

  • either the thread has died, and isAlive() will be false 线程已经死亡,isAlive()将为false
  • or the thread has not died yet but the delay has elapsed, and isAlive() could be true. 或线程尚未死亡,但延迟已经过去,isAlive()可能是真的。 That is possible, but is extremely unlikely, given that the thread has 5 seconds to do its simple job of printing to the console. 这是可能的,但是极不可能,因为线程有5秒的时间来完成打印到控制台的简单工作。

Notice that although the (JDK 7) documentation for Thread.join(long) says 请注意,尽管Thread.join(long)的(JDK 7)文档说明了

Waits at most millis milliseconds for this thread to die. 最多等待millis毫秒该线程终止。

It also continues with 它还继续

This implementation uses a loop of this.wait calls conditioned on this.isAlive . 此实现使用this.wait调用this.isAlive

And Thread.isAlive says: Thread.isAlive说:

A thread is alive if it has been started and has not yet died. 如果线程已经启动并且尚未死亡,则该线程处于活动状态。

So with your code: 所以用你的代码:

  • When calling t1.isAlive() , it is always false since you joined after starting the thread (from the constructor). 调用t1.isAlive() ,由于您在启动线程后(从构造函数)加入,因此它始终为false
  • When calling t2.isAlive() , it is most of the time true since 当调用t2.isAlive() ,大部分时间true
    • you joined before starting the thread (in the constructor), which returns immediately 你在启动线程之前加入了(在构造函数中), 它立即返回
    • the thread has just started (in the constructor) 线程刚刚启动(在构造函数中)

So to answer your question 所以回答你的问题

It seems it can not be but could one of the t1 be alive ? 这似乎也不能,但可以在一个t1活着?

For t1 , no , as long as you wait more than the time it takes it to run. 对于t1 ,只要你等待的时间超过它运行的时间。 For t2 , yes . 对于t2是的

Your t1.isAlive() will always be false. 你的t1.isAlive()总是假的。 The thread you are executing takes a millisecond to run. 您正在执行的线程需要一毫秒才能运行。 You are calling t1.join(5000) which joins that thread with the current thread once it dies . 你正在调用t1.join(5000) ,它会在当前线程死亡时将该线程与该线程连接起来 Since it always runs quicker than 5 seconds then it is always dead by the time it reaches your check for whether it is alive or not. 由于它总是以超过5秒的速度运行,因此它在到达您检查它是否存活时总是死亡。

Your t2.isAlive() will always be true. 你的t2.isAlive()将永远是真的。 On the t2 thread you are calling join in the constructor before you call the start method. 在t2线程上,在调用start方法之前,您正在构造函数中调用join。 Since a thread is always dead until the start method is called that join in the constructor returns immediately. 由于线程始终是死的,直到调用start方法,构造函数中的join才会立即返回。 Which then allows start to be called. 然后允许开始调用。 Even though start is called on a thread it does not mean that it executes right away. 即使在线程上调用start,也不意味着它立即执行。 It just marks it as available for execution and the thread scheduler will start it up at some point in the future. 它只是将其标记为可执行,并且线程调度程序将在未来的某个时刻启动它。 Since you call t2.isAlive() immediately after the constructor it will always be true since the current thread won't be swapped out yet. 由于你在构造函数之后立即调用t2.isAlive()因为当前线程不会被换出,所以它总是为真。

With your code, t1 threads will certainly always print "I'm not alive", and t2 , "I'm alive". 使用你的代码, t1线程肯定会打印“我不活着”,而t2 ,“我还活着”。

For t2 threads, it is weird to call this.join(...) before starting the thread, since (as a complement to what @JB pointed out), the join() doc says 对于t2线程,在启动线程之前调用this.join(...)是很奇怪的,因为(作为@JB指出的补充), join() doc

This implementation uses a loop of this.wait calls conditioned on this.isAlive. 此实现使用this.wait调用this.isAlive的循环。

And, since the thread is not started yet, the join has no effect and returns immediately. 并且,由于线程尚未启动,因此连接无效并立即返回。

But your question is on what can make t1 alive. 但你的问题是什么可以使t1活着。 Just add a Thread.sleep(6000) in the run() method, and you will see the thread as alive. 只需在run()方法中添加一个Thread.sleep(6000) ,您就会看到该线程处于活动状态。 It means that if the task (DB request, ...) done by the thread is longer than the timeout set in the join() , then the answer is "yes, t1 can be alive". 这意味着如果线程完成的任务(DB请求,...)长于join()设置的超时,则答案为“是,t1可以存活”。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM