开发者

Need a Java based interruptible timer thread

开发者 https://www.devze.com 2022-12-31 00:06 出处:网络
I have a Main Program which is running a script on the target device(smart phone) and in a while loop waiting for stdou开发者_StackOverflow社区t messages. However in this particular case, some of the

I have a Main Program which is running a script on the target device(smart phone) and in a while loop waiting for stdou开发者_StackOverflow社区t messages. However in this particular case, some of the heartbeat messages on the stdout could be spaced almost 45secs to a 1minute apart.

something like:

stream = device.runProgram(RESTORE_LOGS, new String[] {});
stream.flush();
String line = stream.readLine();
while (line.compareTo("") != 0) {
    reporter.commentOnJob(jobId, line);
    line = stream.readLine();
}    

So, I want to be a able to start a new interruptible thread after reading line from stdout with a required a sleep window. Upon being able to read a new line, I want to be able to interrupt/stop(having trouble killing the process), handle the newline of stdout text and restart a process.

And it the event I am not able to read a line within the timer window(say 45secs) I want to a way to get out of my while loop either.

I already tried the thread.run, thread.interrupt approach. But having trouble killing and starting a new thread.

Is this the best way out or am I missing something obvious?


It looks like the implementation of System.in varies considerably across platforms and, in particular, doesn't always offer interruptibility or asynchronous closure.

Here is a workaround that doesn't rely on those features, but at the cost of failing to clean up properly; if input isn't received before the timeout expires, the Consumer thread is left in a blocking read().

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;

class InterruptInput
{

  private static final String EOF = new String();

  private final SynchronousQueue<String> pipe = new SynchronousQueue<String>();

  private final BufferedReader input;

  private final long timeout;

  InterruptInput(BufferedReader input, long timeout)
  {
    this.input = input;
    this.timeout = timeout;
  }

  public static void main(String... argv)
    throws Exception
  {
    BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    InterruptInput input = 
      new InterruptInput(in, 5000);
    input.read();
  }

  void read()
    throws InterruptedException
  {
    System.out.println("Enter lines of input (or empty line to terminate):");
    Thread t = new Consumer();
    t.start();
    while (true) {
      String line = pipe.poll(timeout, TimeUnit.MILLISECONDS);
      if (line == EOF)
        break;
      if (line == null) {
        System.out.println("Input timed-out.");
        t.interrupt();
        break;
      }
      System.out.println("[input]: " + line);
    }
  }

  private class Consumer
    extends Thread
  {

    Consumer()
    {
      setDaemon(true);
    }

    @Override
    public void run()
    {
      while (!Thread.interrupted()) {
        String line;
        try {
          line = input.readLine();
        }
        catch (IOException ex) {
          throw new RuntimeException(ex);
        }
        try {
          if ((line == null) || (line.length() == 0)) {
            pipe.put(EOF);
            break;
          }
          else {
            pipe.put(line);
          }
        }
        catch (InterruptedException ex) {
          break;
        }
      }
    }
  }

}


that sure seems like a more elegant solution, especially given I haven't used ScheduledExecutorService before. But I'm still struggling to put all the pieces together though! I'm not sure if and when worker invoked for its 45sec countdown? Also, my intention is for such a worker to restart the countdown once it encounters a line of stdout, essentially resetting the countdown to a fresh 45sec window. Does that help clarify.

While I work to incorporate ScheduledExecutorService into my solution, here's the entire sample code i've been using to replicate it using the threads. Lemme know if I you get it to sooner than I can. I am able to invoke a thread on every newline of stdout I come across, but cannot gracefully handle the case when no interruption occurs for the declared time window :( Hope the comments in the code detailed enough to convey my intentions, else pls let me know and I could clarify:

import java.io.BufferedReader;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.channels.Channels;

public class InterruptInput {   
    static BufferedReader in = new BufferedReader(
            new InputStreamReader(
            Channels.newInputStream(
            (new FileInputStream(FileDescriptor.in)).getChannel())));
    boolean TimeUp = false;

    public static void main(String args[]) {
        try {

            System.out.println("Enter lines of input (user ctrl+Z Enter to terminate):");
            System.out.println("(Input thread will be interrupted in 10 sec.)");
            // interrupt input in 10 sec

            String line = in.readLine();
            while ((line.compareTo("") != 0)) {
            System.out.println("Read line:'"+line+"'");
        TimeOut ti = new TimeOut();
        Thread t = new Thread(ti);
        t.start();
        if((line = in.readLine()) != null) {
            t.interrupt();
            }
            }
        System.out.println("outside the while loop");
        } catch (Exception ex) {
            System.out.println(ex.toString()); // printStackTrace();
        }
    }

    public static class TimeOut extends Thread {
        int sleepTime = 10000;
        private volatile Thread threadToInterrupt;    
        public TimeOut() {
            // interrupt thread that creates this TimeOut.
            threadToInterrupt = Thread.currentThread();
            setDaemon(true);
        }

    public void run() {
        System.out.println("starting a new run of the sleep thread!!");
            try {
                sleep(10000); // wait 10 sec
            } catch(InterruptedException ex) {/*ignore*/
        System.out.println("TimeOut thread interrupted!!");
        //I need to exit here if possible w.out executing
            //everything after the catch block
        }
           //only intend to come here when the 10sec wait passes
           //without interruption. Not sure if its plausible

        System.out.println("went through TimeOut without interruption");
        //TimeUp = true;
        }
    }
}
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号