我有一个主程序,它在目标设备(智能手机)上运行脚本,并在while循环中等待stdout消息。但是在这种特殊情况下,stdout上的一些心跳消息可以间隔45秒到1分钟。
类似的东西:
stream = device.runProgram(RESTORE_LOGS, new String[] {});
stream.flush();
String line = stream.readLine();
while (line.compareTo("") != 0) {
reporter.commentOnJob(jobId, line);
line = stream.readLine();
}
所以,我希望能够在从stdout读取具有所需睡眠窗口的行后启动新的可中断线程。在能够读取新行时,我希望能够中断/停止(无法终止进程),处理stdout文本的换行符并重新启动进程。
事件我无法在计时器窗口中读取一行(比如说45secs)我想要一种方法摆脱我的while循环。
我已经尝试过thread.run,thread.interrupt方法。但是无法杀死并开始新线程。
这是最好的出路还是我错过了一些明显的东西?
答案 0 :(得分:2)
看起来System.in
的实现在不同平台之间存在很大差异,特别是并不总是提供可中断性或异步关闭。
这是一种不依赖于这些功能的解决方法,但代价是无法正常清理;如果在超时到期之前未收到输入,则Consumer
主题将保留在阻止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;
}
}
}
}
}
答案 1 :(得分:0)
这肯定是一个更优雅的解决方案,特别是考虑到之前我没有使用过ScheduledExecutorService。但是我仍然在努力把所有的东西拼凑起来!我不确定工人是否以及何时调用其45秒倒计时?此外,我的目的是让这样的工作人员在遇到stdout线时重新开始倒计时,实际上将倒计时重置为新的45秒窗口。这有助于澄清。
当我努力将ScheduledExecutorService合并到我的解决方案中时,这里是我用来使用线程复制它的整个示例代码。 Lemme知道我能不能尽快得到它。我能够在我遇到的stdout的每个换行符上调用一个线程,但是当声明的时间窗口没有发生中断时,不能优雅地处理这个案例:(希望代码中的注释足够详细以表达我的意图,否则请让我知道,我可以澄清一下:
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;
}
}
}