• Post Reply Bookmark Topic Watch Topic
  • New Topic

Starting threads in constructors  RSS feed

 
Stevens Miller
Bartender
Posts: 1445
30
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Okay, now I really am baffled. This is way off-topic (well, it was until it got split into the start of this new thread), but I'm hoping you can give me a similar tutorial about a "member reference." At Lines 16-23 of MyPanel, NetBeans does point out to me that I can use a lambda, converting this:

to this:

But it also says I can use a "member reference," which ends up looking like this:

I have never heard of a member reference before. There's no mention of it in Core Java, 9th ed.
What in the world is a member reference?
 
Charles D. Ward
Ranch Hand
Posts: 99
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Alaric Mustoe wrote:Well then could you give me an example of how to import and define movement for the image?


Stevens Miller wrote:
Tip: In Java, the word "import" has a very specific meaning, which has nothing to do with what you have described. So, let's use "read" (or "open," or "load") instead of "import," when you are talking about gaining access to the contents of the image file.


I think you should focus on learning basic Java first and then move onto GUI stuff/animation/whatever.
 
Campbell Ritchie
Marshal
Posts: 56546
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Stevens Miller wrote:. . . There's no mention of it in Core Java, 9th ed.
. . .
No, that book was written before Java8.

You can use the method in the functional interface to call a method. You can simply write the method name but rather than writing
-> this.repaint(foo, bar, baz, biz)
… you can infer the however many arguments there are and simply write the name of the method.
this:: repaint
You use the double colon operator (which I think is stolen from C++ but I might be mistaken) rather than a dot. In the case of repaint there are usually no arguments. For other methods, taking arguments, you presume that you have an argument to pass. In the case of a Stream that would be each element of the Stream. So a Stream<Foo> might end with
...forEach(System.out::println)
That means take each Foo object and pass it to System.out.println. Usually a Stream passes one object at a time and you can pass that to a method which can accept it (usually taking one parameter).

You can even pass such arguments to constructors. You write the name of the class then :: then the keyword new.
 
Stevens Miller
Bartender
Posts: 1445
30
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Stevens Miller wrote:There's no mention of it in Core Java, 9th ed.
What in the world is a member reference?

My turn to feel silly: Core Java, 9th ed., is about Java 7, not 8.

Goodness, are we expected to go out and buy a new Core Java for US$65 every year now? Copying all my highlights and marginal notes is getting to be a pain. Why can't they do it in a three-ring binder, and we can just subscribe to the updates?
 
Stephan van Hulst
Saloon Keeper
Posts: 7991
143
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Stevens, I strongly discourage calling pack() in a class' constructor. This method may spawn new threads, and you should never spawn threads from a constructor.
 
Campbell Ritchie
Marshal
Posts: 56546
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

You can get Horstmann's Java8 for the Really Impatient,
Java8 in Action by Urma Fusco and Mycroft,
Java Lambdas by Maurice Naftalin,
and probably quite a lot of other books. There is even this.

Or:

Yes, Pearsons would like you to pay $65 every other year.
 
Stevens Miller
Bartender
Posts: 1445
30
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell Ritchie wrote:You can get Horstmann's Java8 for the Really Impatient

Yes, Pearsons would like you to pay $65 every other year.


I just ordered that one. Looks like Horstmann wrote it for just the purpose we are discussing.

I actually wouldn't mind shelling out that much green every year. It's the danged notes I have to copy. I love the book, but not everything makes perfect sense to me in his wording. When I figure such a passage out, I add my own notes in the margins. When I upgraded from the 8th ed. to the 9th, my wife and I went through the old text, laboriously finding every single addition I had made, transcribing them into the new one. I do not look forward to doing that very many more times
 
Stevens Miller
Bartender
Posts: 1445
30
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Stephan van Hulst wrote:Stevens, I strongly discourage calling pack() in a class' constructor. This method may spawn new threads, and you should never spawn threads from a constructor.


Stephan, that code is actually lifted from the IDE-generated code that NetBeans produced when I added a new class derived from JFrame to my project. Netbeans always puts a call to pack in a method it creates (called initComponents), which is called by the constructor of the JFrame's subclass. You can't even edit initComponents (though you could take out the call to it from the constructor, which would mean the GUI you created in the IDE would never be created).

Even the simpler examples in Core Java, 9th ed. (that don't use all the GUI gobbledegook) call pack from constructors. Here's a fragment from Listing 7.6, on page 380:


What's the down-side to creating threads in a constructor?
 
Campbell Ritchie
Marshal
Posts: 56546
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Stevens Miller wrote:. . . my wife and I went through the old text . . .
How do you persuade your wife to do such things?
 
Stevens Miller
Bartender
Posts: 1445
30
C++ Java Netbeans IDE Windows
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell Ritchie wrote:
Stevens Miller wrote:. . . my wife and I went through the old text . . .
How do you persuade your wife to do such things?

I think she regards the fact that I do them as a kind of carnival sideshow performance art, and joining me sometimes is a form of audience participation.
 
Dave Tolls
Ranch Foreman
Posts: 3061
37
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator


This annoys me a bit. You see it everywhere, and, frankly, it's wrong.
There is almost never a reason to extend JFrame.
All the common examples you see that do it don't actually add anything to the JFrame.
They aren't extending the functionality at all, they're merely using it.
It's akin to extending ArrayList to prepopulate it with entries...
</rant>
 
Stephan van Hulst
Saloon Keeper
Posts: 7991
143
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Stevens Miller wrote:Stephan, that code is actually lifted from the IDE-generated code that NetBeans produced when I added a new class derived from JFrame to my project. Netbeans always puts a call to pack in a method it creates (called initComponents), which is called by the constructor of the JFrame's subclass.

That's a real shame. If you call pack() from a constructor, make sure it's the last instruction, and make sure that the class is final.

What's the down-side to creating threads in a constructor?

Because it allows code to access your object in an inconsistent state. When you call pack(), the EDT will start running and may start performing actions on your component, which has not been fully initialized yet. It's the same issue that arizes when you call a non-final instance method from your constructor, or when you pass 'this' to any other method call:


 
Dave Tolls
Ranch Foreman
Posts: 3061
37
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Stephan van Hulst wrote:When you call pack(), the EDT will start running and may start performing actions on your component, which has not been fully initialized yet.


Which sort of reinforces what I said above.
Don't extend JFrame...
 
Campbell Ritchie
Marshal
Posts: 56546
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Moving to our GUIs forum.
 
Stevens Miller
Bartender
Posts: 1445
30
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Stephan van Hulst wrote:
Stevens Miller wrote:
What's the down-side to creating threads in a constructor?

Because it allows code to access your object in an inconsistent state. When you call pack(), the EDT will start running and may start performing actions on your component, which has not been fully initialized yet. It's the same issue that arizes when you call a non-final instance method from your constructor, or when you pass 'this' to any other method call...

Wow.

That is mind-blowing.

I get how passing this is problematic (because it refers to an instance not guaranteed to be fully constructed until after the constructor returns). And I see how your example shows that calling a method that isn't final can lead to the same problem (really great example, btw). Likewise, a new thread might attempt to reference the object before it's fully constructed, but that's one issue I'm still confused over, a bit. That's because it seems to me that any thread might attempt to access an object that isn't fully initialized, and that the same synchronization mechanisms one uses to avoid that would solve the problem, regardless of whether or not the "offending" thread had been created while the constructor was executing or not.

Moreover, here's my real concern: if harmless old pack() is too dangerous to use inside a constructor, isn't everything too dangerous to use? I mean, how do I know if a parent method can be trusted to not start threads and not pass this to any other method? If those are both things to avoid, then it seems one must exclude all method calls from one's constructors, or else have certain knowledge that no method will start a thread or publish this. The only way I know of to obtain such knowledge would be to limit one's constructor to methods one wrote oneself (or, at least, had the source code for), including all methods invoked anywhere down the call stack before the constructor returned.

Your explanation shows why the risks are real, but that leaves me puzzled about a lot of the Java books I've read. This seems awfully important, yet I've missed it until now.

Just how does one know what is safe to call from a constructor? Is any method sure to be safe to call from a constructor, if you don't have the source?
 
Campbell Ritchie
Marshal
Posts: 56546
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
What makes you think pack() is harmless? If you are changing the size of components while simultaneously adding others, you will get a very peculiar appearance.
 
Stevens Miller
Bartender
Posts: 1445
30
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell Ritchie wrote:What makes you think pack() is harmless? If you are changing the size of components while simultaneously adding others, you will get a very peculiar appearance.

I was being deliberately disingenuous. Stephan and Dave have made some really good points. (In fact, I just went back to some simple code generated by NetBeans and confirmed that it is very easy to move the call to the method that builds the GUI outside the constructor, thus solving the problem Stephan pointed out, and proving that what Dave said makes sense: you don't really need to subclass JFrame just to have a window on the screen.)

But I'm back to my last question: what is safe to call from a constructor? Anything?
 
Dave Tolls
Ranch Foreman
Posts: 3061
37
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Stevens Miller wrote:
But I'm back to my last question: what is safe to call from a constructor? Anything?


A final method owned by the class in question (ie not inherited).
And that assumes there's nothing in the method that you wouldn't be happy having directly in the constructor itself.
 
Stevens Miller
Bartender
Posts: 1445
30
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Dave Tolls wrote:
Stevens Miller wrote:
But I'm back to my last question: what is safe to call from a constructor? Anything?


A final method owned by the class in question (ie not inherited).


This?


 
Stevens Miller
Bartender
Posts: 1445
30
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Actually, I see you already addressed my point with this caveat:
Dave Tolls wrote:
And that assumes there's nothing in the method that you wouldn't be happy having directly in the constructor itself.

This goes back to my concern that you must somehow be sure that, even if your method doesn't start a thread or publish this, nothing ever called as a result of your method starts a thread or publishes this. And the only way to be sure of that would, I think, be to refrain from calling anything for which you did not have the source (from which you could confirm that it never started a thread nor published this). Is there any other way to be sure what you're calling is safe?
 
Stephan van Hulst
Saloon Keeper
Posts: 7991
143
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Stevens Miller wrote:Likewise, a new thread might attempt to reference the object before it's fully constructed, but that's one issue I'm still confused over, a bit. That's because it seems to me that any thread might attempt to access an object that isn't fully initialized, and that the same synchronization mechanisms one uses to avoid that would solve the problem, regardless of whether or not the "offending" thread had been created while the constructor was executing or not.

There are two scenarios here. Either the thread spawned has nothing to do with the object being created, or it does. In the first case, why start it in the constructor at all? In the second case, the object is not guaranteed to be in a consistent state until the constructor finishes running. That's because by definition, everything inside the constructor is related to construction of the object, right? So by definition, any thread started inside a constructor will perform operations on an inconsistent object. Like you said, you can perform manual synchronization to avoid issues, but Java already has a very cheap synchronization mechanism: when the constructor finishes, threads spawned afterwards are guaranteed to see a well-behaved object!

I mean, how do I know if a parent method can be trusted to not start threads and not pass this to any other method? If those are both things to avoid, then it seems one must exclude all method calls from one's constructors, or else have certain knowledge that no method will start a thread or publish this. The only way I know of to obtain such knowledge would be to limit one's constructor to methods one wrote oneself (or, at least, had the source code for), including all methods invoked anywhere down the call stack before the constructor returned.

Exactly.

Just how does one know what is safe to call from a constructor? Is any method sure to be safe to call from a constructor, if you don't have the source?

Yes! You can call methods on things other than this. In my next post I will exhibit a well-behaved Swing form that I usually use to start an application with. It doesn't call any methods that operate on this, or are accessible to other classes.
 
Stevens Miller
Bartender
Posts: 1445
30
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Stephan van Hulst wrote: In my next post I will exhibit a well-behaved Swing form that I usually use to start an application with. It doesn't call any methods that operate on this, or are accessible to other classes.


But how do you know that a method does not operate (and does not result in some operation) on this?
 
Stephan van Hulst
Saloon Keeper
Posts: 7991
143
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
 
Stephan van Hulst
Saloon Keeper
Posts: 7991
143
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Stevens Miller wrote:But how do you know that a method does not operate (and does not result in some operation) on this?


Because methods don't have access to this unless you pass it to them, or call them on it.
 
Stephan van Hulst
Saloon Keeper
Posts: 7991
143
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
In this above code, the only part where I leak 'this' is when I add listeners to the frame. Theoretically, addWindowListener() could invoke listener.windowClosing() and thus this.confirmAndExit() before the constructor technically finished running. However, I consider my object to be in a consistent state after the call to initComponents(), and at that time no non-final method that doesn't belong to MyForm has had access to this.
 
Stevens Miller
Bartender
Posts: 1445
30
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hey, that's awesome! I think I almost get it: a constructor must not start a thread, call an inherited method, call its own non-final (that is, overrideable) method, nor call any method that could result in any of things from happening. This means the constructor can safely call its own final methods (that adhere to the foregoing restrictions), and can call the methods of any instance references it holds (since those methods will refer to their own instances with this, and don't have access to the construtor's this).

But, one thing still eludes me: I see you've moved the call to pack to a safe place: MyForm's show method, which you are not calling until MyForm's constructor returns. That keeps the new MyForm object safe from any threads pack might start. But your constructor, via its calls to initComponents and addListeners makes calls to methods in several other classes. How can you be sure none of those calls start any threads?
 
Stevens Miller
Bartender
Posts: 1445
30
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Stephan van Hulst wrote:In this above code, the only part where I leak 'this' is when I add listeners to the frame. Theoretically, addWindowListener() could invoke listener.windowClosing() and thus this.confirmAndExit() before the constructor technically finished running. However, I consider my object to be in a consistent state after the call to initComponents(), and at that time no non-final method that doesn't belong to MyForm has had access to this.

If one were going to be religious about this, you could just move the call to addListeners to your main method, no?
 
Stephan van Hulst
Saloon Keeper
Posts: 7991
143
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Stevens Miller wrote:If one were going to be religious about this, you could just move the call to addListeners to your main method, no?

Yes

But your constructor, via its calls to initComponents and addListeners makes calls to methods in several other classes. How can you be sure none of those calls start any threads?

Swing guarantees this.
 
Stephan van Hulst
Saloon Keeper
Posts: 7991
143
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Stephan van Hulst wrote:Swing guarantees this.

Actually, AWT guarantees this: http://docs.oracle.com/javase/8/docs/api/java/awt/doc-files/AWTThreadIssues.html#ListenersThreads
Listeners and threads

Unless otherwise noted all AWT listeners are notified on the event dispatch thread. It is safe to remove/add listeners from any thread during dispatching, but the changes only effect subsequent notification.
For example, if a key listeners is added from another key listener, the newly added listener is only notified on subsequent key events.


This means that adding and removing listeners will only call listeners on future events. As long as you can guarantee that future events don't happen prematurely (by refraining from calling pack() and setVisible()), adding listeners is safe!
 
Stephan van Hulst
Saloon Keeper
Posts: 7991
143
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
As for other methods (let's say, textField.setText()): Even if they spawn new threads, they don't have access to your object!
 
Stephan van Hulst
Saloon Keeper
Posts: 7991
143
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I made a short rule.

A constructor must not leak any references to the object being constructed. This means the following things are prohibited:
  1. Calling instance methods (inherited or not) that are not private or effectively final, or that do any of the things described in points 1, 2 and 3.
  2. Passing 'this' as an argument to any method that is not private or that does any of the things described in points 1, 2 and 3.
  3. Spawning threads that do any of the things described in points 1, 2 and 3.
 
Stevens Miller
Bartender
Posts: 1445
30
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Stephan van Hulst wrote:This means the following things are prohibited:
  1. Calling instance methods (inherited or not) that are not private or effectively final, or that do any of the things described in points 1, 2 and 3.
  2. Passing 'this' as an argument to any method that is not private or that does any of the things described in points 1, 2 and 3.
  3. Spawning threads that do any of the things described in points 1, 2 and 3.


Okay, I'm keeping up with you on Points 1 and 2. But I am still unsure about Point 3. That's because I am thinking that the member variable some instance of class A will use to hold a reference to an instance of class B that it creates by calling new B() can be accessed by a thread started in B() and, short of a reference to documentation to the contrary (like you provided with respect to Swing), there seems to be no way to know if this is going to happen.

I'll see if I can cobble up some code that illustrates what I'm confused about. Maybe that will clear my confusion for me.
 
Stephan van Hulst
Saloon Keeper
Posts: 7991
143
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I understand what you mean:

A new instance of A can become inconsistent after it's been constructed, because B spawns a thread that can make it inconsistent after it's been constructed.

The reason why we assume this doesn't happen, is because we trust client classes to be well-behaved. Just like how we shouldn't spawn threads from our constructors, we trust other classes to do the same.

After all, when I call String.toLowerCase(), I trust it not to call System.exit().
 
Stevens Miller
Bartender
Posts: 1445
30
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Just let me check something: Did you mean Line 7 to be this?

It seems to me that (whether Line 7 is correct as it is or not) you've really just got a race condition there, one that should be handled like any other. What I had in mind was something like this:

(And please stay off my back about lambdas, Campell Ritchie; when I'm trying to learn this stuff, I need it spelled out long-hand )

The thread started in tc can (and, again, this is a kind of race condition) get an inconsistent value for s, because its thread might (or might not) access s before tc is fully constructed. On my machine, that code produces

ThreadedClass got there first

But, if you change Line 23 to this:
on machine, the new code produces

Constructor got there first

However, this can only happen because ThreadedClass has access to mc explicitly, which creates the same opportunity for access to a not-yet-fully-contructed instance as does leaking this. So, all I've done here is prove that code that "knows" about an object variable that might or might not refer to a fully constructed instance needs to be synchronized if it might gain access to that variable from any thread other than the one on which that instance is constructed. Which, again, I think is just a synchronization problem.

Which brings me back to pack. Is the problem with pack that it might spawn threads, or is the problem really that it is an inherited method whose threads are virtually certain to make use of this, conceivably before the instance calling it from its constructor (as in my flawed MainFrame class, for example) has been fully constructed?

In other words, while I can see now how leaking this, or writing multi-threaded code that might access a not-fully-constructed instance could fail, I'm still not seeing how the mere fact of a method causing a thread to start in a constructor can be problematic. If that thread has no way to access the instance that spawned it, what can wrong?
 
Stevens Miller
Bartender
Posts: 1445
30
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hey, no fair changing your code after I found a bug in it, Stephan!
 
Mike. J. Thompson
Bartender
Posts: 689
17
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
There isn't anything inherently unsafe about starting a thread in a constructor. It is only unsafe if the thread has access to and makes use of the this reference and the thread is not started as the last call in the constructor. That is why you were advised to make sure pack() was the last call in the constructor if you were calling it in there.

But it makes sense not to do it in case you modify the code in such a way that it stops being threadsafe by mistake.
 
Mike. J. Thompson
Bartender
Posts: 689
17
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Oh, and the code you posted a few posts up has a data race rather than a race condition. Even if the constructor call finishes before the thread starts running it is still possible for it to print "ThreadedClass got there first" because there is no guarantee that the second thread will see the result of the second write to the String variable.
 
Stevens Miller
Bartender
Posts: 1445
30
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Mike. J. Thompson wrote:There isn't anything inherently unsafe about starting a thread in a constructor. It is only unsafe if the thread has access to and makes use of the this reference and the thread is not started as the last call in the constructor. That is why you were advised to make sure pack() was the last call in the constructor if you were calling it in there.

But it makes sense not to do it in case you modify the code in such a way that it stops being threadsafe by mistake.

I think that's really the right analysis, Mike. I found an article by Brian Goetz that seems to be the source of some misunderstanding about this. In the body of the article, he says this:

Brian Goetz wrote:Don't start threads from within constructors
A special case of the problem in Listing 4 is starting a thread from within a constructor, because often when an object owns a thread, either that thread is an inner class or we pass the this reference to its constructor (or the class itself extends the Thread class). If an object is going to own a thread, it is best if the object provides a start() method, just like Thread does, and starts the thread from the start() method instead of from the constructor. While this does expose some implementation details (such as the possible existence of an owned thread) of the class via the interface, which is often not desirable, in this case the risks of starting the thread from the constructor outweigh the benefit of implementation hiding. (underlining added)

Read closely, this reasoning matches yours (and, fwiw, mine), with the result being that his subtitle, "Don't start threads from within constructors," overreaches. It's perfectly okay to start threads from constructors, provided you don't do it in any of the common ways that give that thread access to this.

In his book, "Java Concurrency in Practice," he has a short section on the kinds of bugs that the static code-analyzer, FindBugs, can find. Among them are this entry, on Page 272:

in "Java Concurrency in Practice" Brian Goetz wrote:Starting a thread from a constructor.
Starting a thread from a constructor introduces the risk of subclassing problems, and can allow the this reference to escape the constructor.

That's all he seems to say about it, without any elaboration on what the subclassing problems might be. (I'm guessing he means that programmers writing subclasses won't always know their superclass starts these threads, but, again, it seems to me that there's no way to prevent it, depending on what the superclass calls; as I keep coming back to, you just don't have any sure way to know if a method creates a thread if you don't have the source).

So, it seems to me that Goetz's warning, which is based on the dangers arising when this leaks out of the constructor, have been inadvertently morphed into a general warning against starting threads in constructors, when Goetz's actual point was really that common ways of starting threads (such as anonymous inner classes that implement Runnable) leak this. (For example, here's a site that actually cites "Java Concurrency in Practice," going on to say, "There's nothing wrong with creating a thread object in a constructor or static initializer - just don't start it there.")

The bottom line appears to be that you are right: starting a thread in a constructor is not inherently dangerous, but leaking this is and non-final methods of your class (inherited or otherwise) might do both, so they are not to be called in a constructor.
 
Stevens Miller
Bartender
Posts: 1445
30
C++ Java Netbeans IDE Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Mike. J. Thompson wrote:Oh, and the code you posted a few posts up has a data race rather than a race condition. Even if the constructor call finishes before the thread starts running it is still possible for it to print "ThreadedClass got there first" because there is no guarantee that the second thread will see the result of the second write to the String variable.

Good catch. I think this would fix it:

Not sure I'd call that a data race, though.
 
Mike. J. Thompson
Bartender
Posts: 689
17
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The Java Memory Model calls it a data race ;)
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!