3

Can we call thread_object.start() from within a constructor of this same object?

Is this approach a good idea ?

Paŭlo Ebermann
  • 73,284
  • 20
  • 146
  • 210
Saurabh Gokhale
  • 53,625
  • 36
  • 139
  • 164

5 Answers5

6

You can do that, but it is considered as bad practice. There is one paragraph about starting Threads in constructors in this article.

AS nicerobot stated in the comments, your question seem to be a duplicate of this. Have a look at Heath Borders answer there.

Community
  • 1
  • 1
Nils Schmidt
  • 3,702
  • 6
  • 23
  • 28
  • @Nils: The article only points out the risks in exposing 'this' reference when the object is not in a consistent state yet. In the case of threads, you can do it safely in the ctor by creating a non-inner-class thread, and providing it with the data it needs for running (and not with 'this' reference). – Eyal Schneider May 06 '10 at 11:35
  • Excellent! Reference escaping can is not thread-safe! – Ovidiu Lupas May 06 '10 at 13:10
2

Just out of interest - why do you extend Thread? Why not implement Runnable instead, you get more flexibility (e.g. can be executed within a thread you create or an ExecutorService, which is the preferred method).

ishmeister
  • 599
  • 1
  • 3
  • 8
1

It's a bad practice, since you cannot be sure that the object is fully initialized. Even if you call the start() method at the end of the constructor it may result in a mess.

Be aware that the processor can do things out of order:

1: MyObject(){
2:  aVariable = anyValue;
3:  this.start();
4: }

The processor is free to execute line 3 before line 2 since they aren't related (in a single threaded fashion), so you could end up with uninitalized variables (even final ones), and other unexpected stuff.

Hardcoded
  • 6,476
  • 2
  • 22
  • 20
  • Actually, calling `thread.start()` is in a *happens-before* relationship to everything that happens in the `run()` method, and `aVariable = anyValue` *happens-before* starting the thread by being before it in the constructor. So your particular example is well defined, and will not cause any problems. – Paŭlo Ebermann Aug 31 '11 at 23:18
  • No, since most of us are using out-of-order-processors, nothing is defined. JLS: "It should be noted that the presence of a happens-before relationship between two actions does not necessarily imply that they have to take place in that order in an implementation. If the reordering produces results consistent with a legal execution, it is not illegal." Since those two statements aren't directly affected by each other (accessing the same variable or similar), reordering is allowed. – Hardcoded Sep 02 '11 at 06:57
  • Read the second part of your cited sentence: *If the reordering produces results consistent with a legal execution*. I.e. **it must produce the same results**. The processor can do things out-of-order, but the *happens-before* order is still derived from the *program order* (i.e. the order of the actions in one thread as written in the program) and the synchronization order (certain inter-thread ordering actions, here starting of a thread). (Linking section [17.4.3](http://java.sun.com/docs/books/jls/third_edition/html/memory.html#17.4.3) to 17.4.5 for details for any readers.) – Paŭlo Ebermann Sep 02 '11 at 12:00
  • If the second thread does not access the variable, you can reorder as you want - but there won't be any problem, as this variable is not accessed. If the second thread accesses the variable, the *happens-before* relationship guarantees that it reads the value set in the constructor (if there isn't someone setting another value between). Nothing undefined here. – Paŭlo Ebermann Sep 02 '11 at 12:02
  • How does the processor or the JVM know what will happen in a different thread (maybe at a different processor) at a different method? happen-before is AFAIK associated to the in-method-calls. From that point of view, the implementation would be free to reorder and getting the same result (starting a thread and setting a value). Otherwise there would be a lot of beforehand-tracing and/or some magic involved. ;-) – Hardcoded Sep 02 '11 at 12:29
  • Please read 17.4.5: *happens-before* is the transitive closure of *program order* (intra-thread) and *synchronization order* (inter-thread). I'm not a specialist about JVM implementation, but I suppose whenever there is a synchronization constraint (like starting a thread), the reordering is somehow limited to "nothing which was before the start can now be after". There also will be a cache flush/memory barrier, I suppose. – Paŭlo Ebermann Sep 02 '11 at 12:55
  • This may be a valid point, and reordering might happen far less than it would be possible without breaking the JLS. But I wouldn't trust on a JVM implementation to do so. The JLS only defines that the started thread is run after the start()-Method is executed, but not that start() has to be done after prior actions in the same Thread. Some white or gray spots have just been fixed with the latest JLS version (initializing on volatile-fields, for example), but there are still some remaining. – Hardcoded Sep 05 '11 at 09:48
0

I would suggest to start the thread outside, instead of calling from Constructor. In constructor you should be doing only initialization stuff.

Phanindra
  • 137
  • 1
  • 1
  • 3
-1

As long the thread you're starting doesn't have a reference to this then you're okay. If the thread does have a reference to this (either passed to the thread of indirectly via an inner class) then it's a bad idea to start it from the constructor as the object isn't fully initialized.

Steve Kuo
  • 61,876
  • 75
  • 195
  • 257