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

Reply via email to