The bug you refer to is the reason why Thread.stop(), Thread.resume() and
Thread.suspend() have
been depricated as of JDK 1.2(AKA Java 2). Try using this technique to
stop a thread from
within the run( this was suggested by Sun ).
Example:
In this runnable's run() checks a private boolean variable (shutdown) and
if true does clean-up work and return thereby stopping the thread
immediately . The thread can be shutdown the parent thread by a call to a
synchronized method shutdown(). The Shutdown() method set a private boolean
"shutdown" to true;
// here is the code
package com.chase.dss.server;
import java.net.*;
import java.io.*;
import java.util.*;
public class DSSRecordRecvRunnable implements java.lang.Runnable
{
private DSSTandemFeedLoader parent;
private DSSBlockInserter blkproc;
private Queue recordQueue;
private String processName;
private String feedAddr;
private String feedPort;
private int numRecsPerBlock;
private int numBlksNotified;
private boolean shutdown = false;
/****
* Default Constructor
*
*/
DSSRecordRecvRunnable(DSSTandemFeedLoader parent,
DSSBlockInserter bls,
Queue recordQueue,
String processName,
String feedAddr,
String feedPort,
String numRecsPerBlocks)
{
this.parent = parent;
this.blkproc = bls;
this.recordQueue = recordQueue;
this.processName = processName;
this.feedAddr = feedAddr;
this.feedPort = feedPort;
this.numRecsPerBlock = Integer.parseInt(numRecsPerBlocks);
}
/*****
* Shutdown this thread
*/
public void shutdown()
{
shutdown = true;
}
public void run()
{
int restart = 0;
while (true)
{
try
{
String tName = ((Thread)Thread.currentThread()).getName();
if ( restart == 0 )
{
// first time here
parent.setStatus(tName + " is running...." );
}
else
{
// this is a restart
parent.setStatus(tName + " autorestart[" + restart +
"] is running...." );
}
// Open socket connection to the
// feed service
int iPort = Integer.parseInt(feedPort);
Socket sock = new Socket(feedAddr,iPort);
DataOutputStream sendData = new
DataOutputStream(sock.getOutputStream());
// now connect with feed service sending
// this process' name
sendData.writeBytes(processName);
sendData.flush();
// now get a data input stream and
// start processing records
DataInputStream recvData = new
DataInputStream(sock.getInputStream());
BufferedReader recvDataBuffered = new BufferedReader(new
InputStreamReader(recvData));
int cnt = 0;
Vector rows = new Vector();
// loop until shutdown requested
while(true)
{
// check if thread should shutdown
// close socket now and place any remaining
// records is the queue
if(shutdown == true)
{
// close the socket
sock.close();
// add the remaining records to the queue
recordQueue.insertObject(rows);
parent.setStatus(tName + "- Shutdown
Complete....");
return;
}
DSSTandemFeedRecord trec =
parseRecord(recvDataBuffered);
if ( trec == null )
continue;
// send the records based on the block size
// to the inserter thread and notify the thread
// to start running
if( cnt > numRecsPerBlock )
{
rows.addElement(trec);
recordQueue.insertObject(rows);
cnt=0;
rows = new Vector();
}
else
{
rows.addElement(trec);
cnt++;
}
} // end while
}
catch(ConnectException ce)
{
// restart the recv thread if socket connection
// failed on open
String tName = ((Thread)Thread.currentThread()).getName();
parent.setStatus(tName + "- Connection Exception :" +
ce.getMessage());
restart++;
try
{
((Thread)Thread.currentThread()).sleep(5000);
}
catch(InterruptedException ie)
{
}
}
catch(Exception ie)
{
// print all exception and continue
String tName = ((Thread)Thread.currentThread()).getName();
ie.printStackTrace();
parent.setStatus(tName + "- Exception :" +
ie.getMessage());
}
} // end while ( ENDLESS LOOP )
}
}
Cheers
Chris
Ron Resnick wrote:
> Hello,
>
> I'm using Blackdown's JDK 1.1.6 on Linux 2.0.34 (Redhat).
>
> I'm having strange thread behaviour which (a) might
> somehow be a bug in my code, but I doubt it
> (b) might be a generic
> Java problem, and not due to the Blackdown port
> (c) might already be identified and fixed in 1.1.7.
>
> If it is any of the above categories, I apologize.
>
> I have an applet, which starts off on a main thread in
> init(), and at some point in its lifecycle spawns off
> a new thread in a Runnable object. Later on, the main
> thread invokes stop() on the child thread. Roughly
> 80% of the time, this works correctly - the child thread
> dies like it's supposed to. But about 20% of the time,
> the child thread never dies. In fact, it never enters the
> finalize() method I inserted to 'trap' this problem.
>
> Here's some relevant snippets:
>
> public class jppp extends Applet{
>
> Thread counter = null;
>
> public void init() {
> //... bunch of init stuff...
>
> counter = new Thread(new waitConnect());
> counter.start();
> }
>
> // ... later on, in some event handling code .....
> log ("DEBUG " + Thread.currentThread() +
> ": Stopping the counter thread "+ counter);
> counter.stop();
>
> //....
>
> // waitConnect is a nested class within the applet
> public class waitConnect implements Runnable{
>
> protected void finalize() throws Throwable
> {
> log ("DEBUG " + Thread.currentThread() +
> "In finalizer of waitConnect class");
> }
>
> public void run() {
> // once a new thread starts executing in run, it enters
> // a while(true) loop so lives forever until killed externally
> while (true)
> {
> //...
> if( //test a condition which means this thread should
> // be gone, yet it's still alive)
> {
> log ("DEBUG " + Thread.currentThread() +
> "Uh oh. In while(true) loop, but should be dead");
> }
> //....
> Thread.sleep(1000); //execute main loop every second
> } // end while(true)
> } // end run()
>
> } // end of waitConnect (nested class)
>
> } // end of jppp (applet)
>
> ============================
>
> The length of time between the thread.start() and stop()
> can vary between a few seconds, to as long as 5 or 6 hours.
> Most of the time, the logs I get look like this:
>
> ...
> [10-Dec-98 2:50:08 AM jppp] : DEBUG Thread[AWT-EventQueue-0,5,main]:
> Stopping the counter thread Thread[Thread-9,5,main]
> [10-Dec-98 2:50:08 AM jppp] : DEBUG Thread[Finalizer thread,1,system]In
> finalizer of waitConnect class
> ...
>
> I.e., we see the log of the parent thread stopping the child,
> and the log of the child in the finalizer as it is shut down.
>
> However, occassionally (and usually on runs where the child
> has been alive for several hours), the log is:
>
> [10-Dec-98 12:56:09 PM jppp] : DEBUG Thread[AWT-EventQueue-0,5,main]:
> Stopping the counter thread Thread[Thread-15,5,main]
> [10-Dec-98 12:56:09 PM jppp] : DEBUG Thread[Thread-15,5,main] Uh oh. In
> while(true) loop, but should be dead
> [10-Dec-98 12:56:10 PM jppp] : DEBUG Thread[Thread-15,5,main] Uh oh. In
> while(true) loop, but should be dead
> [10-Dec-98 12:56:11 PM jppp] : DEBUG Thread[Thread-15,5,main] Uh oh. In
> while(true) loop, but should be dead
> [10-Dec-98 12:56:12 PM jppp] : DEBUG Thread[Thread-15,5,main] Uh oh. In
> while(true) loop, but should be dead
> ....
>
> I.e. , the parent has issued the same stop() as previously,
> only the Finalizer in the child never got invoked,
> and the child thread stays alive.
>
> As I say, I suspect a bug in the implementation of stop().
>
> Any ideas? Obviously, I can work around this problem by having
> my child commit suicide in its 'if' detection. But I'm posting
> this, since there may be a more general problem here of wider
> interest.
>
> Regards,
> Ron
>
> --
>
> Ron Resnick
> DiaLogos Incorporated
> http://www.dialogosweb.com