I've encountered a very strange problem with thread synchronization in code
executed by a servlet's init() method. I've included sample code below.
Within my init() method I want to create an object that creates a new thread
that will handle network communications. The main thread needs to block
until the I/O thread notifies it that it has established a valid connection.
I do this by creating an Object that the main thread waits on and the I/O
thread notifies. The problem is that the I/O thread's run() method does not
start executing until the main thread's wait() method times out. If I move
this code from init() into doGet() it works fine.
I've used Threadalyzer to take a look at what's happening and it appears
that the java.lang.Thread.run is blocked waiting to acquire
com.livesoftware.jrun.JRunServletLoader. This object is apparently held
across the object.wait(). This prevents the run method from starting until
the wait completes.
The example code is in three files. WaitTest.java creates the I/O thread
and waits for it to notify objWait. The I/O thread is simulated by calls to
Thread.sleep(). AppTest.java is a simple servlet that creates an instance
of WaitTest inside init() and calls its connect method. What I see in
stderr.log is that the messages from inside the run method don't get
displayed until after the objWait.wait() times out.
AppTest2.java simply moves the WaitTest code from init() to doGet(). When I
run this I see the messages that I'm entering the wait, followed by the
run() method starting and then the object gets notified.
Am I doing something against the rules by creating threads inside the init()
method? Is there any work around for this? Thanks.
----------- AppTest.java ------------------
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
/**
*
*/
public class AppTest extends HttpServlet
{
private WaitTest conn = null;
public void init(ServletConfig config) throws ServletException
{
super.init(config);
try{
conn = new WaitTest();
conn.connect();
}catch(Exception e){
System.err.println("AppTest.init: " + e.toString());
}
}
public void doGet(HttpServletRequest req, HttpServletResponse res) throws
ServletException, IOException
{
res.setContentType("text/html");
PrintWriter out = res.getWriter();
out.println("<html><body><h1>Blah</h1></body></html>");
}
public void destroy()
{
if(conn != null)
conn.disconnect();
}
}
--------------------------------------------
----------- AppTest2.java -----------------
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class AppTest2 extends HttpServlet
{
private WaitTest conn = null;
public void init(ServletConfig config) throws ServletException
{
super.init(config);
}
public void doGet(HttpServletRequest req, HttpServletResponse res) throws
ServletException, IOException
{
try{
conn = new WaitTest();
conn.connect();
}catch(Exception e){
System.err.println("AppTest.init: " + e.toString());
}
res.setContentType("text/html");
PrintWriter out = res.getWriter();
out.println("<html><body><h1>Blah</h1></body></html>");
}
public void destroy()
{
if(conn != null)
conn.disconnect();
}
}
--------------------------------------------
----------- WaitTest.java -----------------
import java.io.*;
public class WaitTest implements Runnable
{
private Thread thrdReader;
private boolean bDisconnecting = false;
private int nTimeout = 15000;
private Object objWait = new Object();
public void connect()
{
try{
thrdReader = new Thread(this);
System.err.println("WaitTest.connect: Starting reader
thread.");
thrdReader.start();
try{
synchronized(objWait){
System.err.println("WaitTest.connect: Waiting
for connection...");
objWait.wait(nTimeout);
System.err.println("WaitTest.connect: Wait
returned.");
}
}catch(InterruptedException e){
System.err.println("WaitTest.connect: " +
e.toString());
}
}catch(Exception e){
}
}
public void disconnect()
{
try{
bDisconnecting = true;
try{
thrdReader.join(30000);
}catch(InterruptedException e){
}
}catch(Exception e){
System.err.println("WaitTest.disconnect: Caught exception. "
+
e.toString());
}finally{
bDisconnecting = false;
}
}
public void run()
{
System.err.println("WaitTest.run: entered.");
while(!bDisconnecting){
try{
Thread.currentThread().sleep(5000);
synchronized(objWait){
objWait.notifyAll();
}
}catch(InterruptedException e){
}
}
System.err.println("WaitTest.run: leaving.");
}
}
--------------------------------------------
------------------------------------------------------------------------------
Archives: http://www.egroups.com/group/jrun-interest/
Unsubscribe: http://www.houseoffusion.com/index.cfm?sidebar=lists&body=lists/jrun_talk
or send a message to [EMAIL PROTECTED] with 'unsubscribe' in the
body.