Java streaming intermittent timer required

I have a main program that runs a script on the target device (smartphone) and in a while loop waiting for a stdout message. However, in this particular case, some heartbeat messages on the standard output may be located at a distance of almost 45 seconds from a distance of up to 1 minute.

sort of:

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 able to start a new intermittent stream after reading a line from stdout with the required sleep window. Having the opportunity to read a new line, I want to be able to interrupt / stop (without having problems with killing the process), process a new line of stdout text and restart the process.

And this is an event in which I cannot read a line in the timer window (say 45 seconds), I want to exit my while loop.

I have already tried the thread.run method, thread.interrupt. But the problem is with killing and launching a new thread.

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

+4
source share
2 answers

It appears that the implementation of System.in varies significantly across platforms and, in particular, does not always provide interruption or asynchronous closure.

The following is a workaround that does not rely on these features, but at the cost of a failed cleanup; if no input is received before the timeout expires, the Consumer thread remains in read() lock.

 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; } } } } } 
+2
source

this seems like a more elegant solution, especially considering that I have not used ScheduledExecutorService before. But I'm still trying my best to collect all the pieces! I'm not sure if and when the worker is being called for his countdown of 45 seconds? Also, I want such a worker to restart the countdown after he met the stdout line, essentially resetting the countdown to a new 45 second window. Does this help clarify.

While I am working on incorporating ScheduledExecutorService into my solution, here is all the sample code that I used to replicate it using threads. Lemme knows if I get it sooner than I can. I can call a thread on every new stdout line that I encounter, but cannot gracefully handle the case where there is no interruption for the declared time window :( I hope the comments in the code are detailed enough to convey my intentions, otherwise PLS will allow me I 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
source

Source: https://habr.com/ru/post/1310181/


All Articles