I have a servlet automatically firing up when the app server starts, and in its init(), I'm making another thread:
init(){ new FooThread().start() }
in FooThread(), i want to periodically check the status of a DB value, then depending on the value, make a web service call. When these two tasks complete, I want the thread to sleep to wait a certain period then repeat. This cycle would just continue forever.
FooThread:
public class FooThread implements Runnable{
Thread t;
FooThread(){
t = new Thread(this, "FooThread");
}
public void start(){
t.start();
}
public void run() {
try{
while(true){
//do the db check, then conditionally do the web services call
logger.info("*** calling sleep() ***");
Thread.sl开发者_如何转开发eep(50000);
logger.info("*** now awake ***");
}
} catch (InterruptedException e) {
System.out.println("*** FooThread interrupted");
}
}
}
Don’t start threads in your constructors because it could lead to race conditions and indeterminate behavior. Instead, call the start()
method after constructing the object.
EDIT:
The reason it's bad is because you may publish the this
pointer before the
constructor has finished.
What you are doing is considered unsafe publication. When -this- reference escapes the constructor you have the possibility of sending a partially constructed object to thread class.
In your example what if your class and the run method looked like this:
public class FooThread implements Runnable{
Thread t;
private int someInt;
private Object someObject;
FooThread(){
t = new Thread(this, "BBSThread");
t.start();
someInt = 10;
someObject = new Object();
}
public void run() {
System.out.println(this.someInt);
System.out.println(this.someObject);
}
}
It is possible there that someInt prints 0 and someObject prints null. Your object is technically constructed but not completed.
You don't need to create a new variable t
inside FooThread
if you subclass from Thread
. An instance of FooThread
then already is the thread. And you don't need to call start()
on it in the constructor.
A proper use of FooThread
inside init()
would be:
FooThread ft = new FooThread();
ft.start(); // calls run() inside FooThread
In the code you lined out above the constructor of FooThread
doesn't need any logic, run()
looks fine.
精彩评论