4

I have read some SO question and docs before but do not find my response :

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 ? What about t2 ? What happend when I call join() after start()

For information, I am using :

  • JVM: Java HotSpot(TM) Client VM (20.45-b01, mixed mode, sharing)
  • Java: version 1.6.0_45, vendor 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

Community
  • 1
  • 1
Manu
  • 809
  • 1
  • 9
  • 28
  • 7
    Two notes, though they don't answer your question: Firstly, why are you joining on the thread before you even start it, in the constructor? And secondly, you actually shouldn't start a thread from its constructor. The reasons are a bit subtle, but basically a bunch of convenient-to-reason-about threading guarantees go out the window if you do that. You should always first construct it, and then start it. – yshavit Apr 21 '15 at 13:59
  • 2
    [It is recommended to implement Runnable instead of extend Thread](http://stackoverflow.com/questions/541487/implements-runnable-vs-extends-thread). I suggest you first follow good practices for multi-threading in your code then rewrite your test. – m0skit0 Apr 21 '15 at 14:05
  • 2
    Ditto what yshavit said: Calling `this.start()` from within the constructor is a _Bad Idea_. It potentially allows the new thread's run() method to see the Thread object in an uninitialized state. Move the start() calls into your MyClass() constructor. And calling .join() before calling .start()? Have you read the documentation? – Solomon Slow Apr 21 '15 at 14:25
  • 1
    @jameslarge Without mentioning he's not even calling `super()`. – m0skit0 Apr 21 '15 at 14:29
  • With your modifications, what is precisely your question now? What are you trying to achieve exactly? – Didier L Apr 21 '15 at 18:09
  • @DidierL I try/hope to be more precise... I have to choose the better response now – Manu Apr 22 '15 at 09:41

4 Answers4

2

The documentation of isAlive() says:

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

The documentation of join() says:

Waits at most millis milliseconds for this thread to die

So, after join() returns,

  • either the thread has died, and isAlive() will be false
  • or the thread has not died yet but the delay has elapsed, and isAlive() could be true. That is possible, but is extremely unlikely, given that the thread has 5 seconds to do its simple job of printing to the console.
JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
1

Notice that although the (JDK 7) documentation for Thread.join(long) says

Waits at most millis milliseconds for this thread to die.

It also continues with

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

And Thread.isAlive says:

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).
  • When calling t2.isAlive(), it is most of the time true since
    • 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 ?

For t1, no, as long as you wait more than the time it takes it to run. For t2, yes.

Didier L
  • 18,905
  • 10
  • 61
  • 103
  • Does 'loop of this.wait calls conditioned on this.alive' mean that if `isAlive()==false` then the thread is re-turn to alive'like state until waiting for 5 seconds in my case ? Is this available for Java v1.6 ? – Manu Apr 21 '15 at 15:31
  • 1
    I'm not sure to understand your comment, but if `!isAlive()`, then `join(…)` returns immediately, without waiting. The behaviour is the same in Java 6, but the documentation has been updated in Java 7 to reflect this behaviour (looping on `isAlive()`). – Didier L Apr 21 '15 at 15:43
1

Your t1.isAlive() will always be false. 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. 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.

Your t2.isAlive() will always be true. On the t2 thread you are calling join in the constructor before you call the start method. Since a thread is always dead until the start method is called that join in the constructor returns immediately. Which then allows start to be called. Even though start is called on a thread it does not mean that it executes right away. 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.

markbernard
  • 1,412
  • 9
  • 18
1

With your code, t1 threads will certainly always print "I'm not alive", and t2, "I'm alive".

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

This implementation uses a loop of this.wait calls conditioned on 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. Just add a Thread.sleep(6000) in the run() method, and you will see the thread as alive. 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".

T.Gounelle
  • 5,953
  • 1
  • 22
  • 32
  • Do you recommand to : construct the thread (`Thread t = new Thread();`), then start it (`t.start();`) and finally call join (`t.join(5000);`) ? In this order ? Or better is `t.join(5000);t.start();` ? – Manu Apr 21 '15 at 15:44
  • 1
    I don't know what you are trying to do, but as said, when calling `this.join(5000); this.start();` in the constructor, `join()` won't do anything. – T.Gounelle Apr 21 '15 at 15:59