Question

I have a thread that is started when my web application starts (contextInitialized). All this thread does is, read data from the socket.

public void run() {
    while (!Thread.currentThread().isInterrupted() || !this.isInterrupted()
            || !stopped) {
        try {
            System.out.println("************polling..............");
            readData();
            Thread.sleep(300);
        } catch (InterruptedException e) {
            System.out.println("interrupted... ");
            Thread.currentThread().interrupt();
            break; //required?
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

   public void shutdown() {
    stopped = true;
    }
    // I know I'm blocking here.
    private void readData() {
          if (null == socket)
             throw new ConnectionException();
          if (inStream == null) {
             inStream = this.socket.getInputStream();
          }
          byte[] buff = new byte[length];
          int receiveLength = 0;
          do {
             try {
              receiveLength = inStream.read(buff, 0, length);
              } catch (Exception e) {
               e.printStackTrace();
              }

             } while (receiveLength <= 0);
       }

I call interrupt() method in the contextDestroyed, but this thread fails to stop, why is that?

    if (poller != null) {
        ((Poller) poller).shutdown();
        poller.interrupt();
                    // should I need to do this?
        while (poller.isAlive()) {
            ;
        }
    }
Was it helpful?

Solution

If I were doing this, this is what I would do it using different library stuff:

The real problem is this loop inside readData:

do {
    try {
        receiveLength = inStream.read(buff, 0, length);
    } catch (Exception e) {
        e.printStackTrace();
    }
} while (receiveLength <= 0);

If you use a loop here, it will keep reading even if there is nothing to read, rather than returning to the outer loop with the delay. Get rid of the loop. Also, move all the initialization in the method to the constructor.

Here is how I would do this:

class ConnectionReader implements TimerTask {

    InputStream inStream;
    byte[] buf;

    public ConnectionReader(Socket socket, int length){
        if (null == socket)
            throw new ConnectionException();
        if (inStream == null) {
            inStream = this.socket.getInputStream();
        }
        buf = new byte[length]
    }

    @Override
    public void run() {
        try {
            System.out.println("polling...");
            readData();
        } catch (InterruptedException e) {
            System.out.println("interrupted...");
            cancel()
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    private void readData() {
       try {
            receiveLength = inStream.read(buff, 0, length);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

To start it, use a Timer set for the desired 300ms delay:

TimerTask readTask = new ConnectionReader(this.socket, length);
new Timer().schedule(readTask,0,300);

To cancel it, you just call readTask.cancel().

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top