取消 Eclipse 插件作业
Cancel eclipse plugin job
我 运行 在 eclipse 插件中 Job
一个执行长操作而没有太多输出的进程。
如果用户请求,我希望能够取消 Job
,但是通过下面的实现,Job
不会停止,除非进程将某些内容打印到输出流。
Process process = new ProcessBuilder(args).start();
Scanner scanner = new Scanner(
(new InputStreamReader(
process.getInputStream(), UTF_8_CHARSET)));
while (scanner.hasNext())
{
if (monitor.isCanceled() {
// user canceled the job, destroy the process to return
process.destroy();
break;
}
CONSOLE.getStream().println(scanner.nextLine());
}
try {
process.waitFor();
} catch (InterruptedException e) {
Activator.log(ERROR, e.getMessage(), e);
} finally {
process.destroyForcibly();
}
我是否有其他选项来处理作业的取消并更快地停止进程而不是等待新的换行?
而不是 Scanner
使用 BufferedReader
提供 ready
方法,这是一种 non-blocking 告诉你是否有东西要阅读而不是使用的方法扫描器的 nextLine()
在实际读取某些内容之前一直处于阻塞状态。
小示例实现:
volatile static boolean stop = false;
public static void main(String[] args) throws InterruptedException
{
// Create a new thread that reads input from System.in
new Thread(() -> {
BufferedReader read = new BufferedReader(new InputStreamReader(System.in));
while (!stop)
{
try
{
// If there is something to read read it and print it
if (read.ready())
{
System.out.println(read.readLine());
}
}
catch (IOException e)
{
// Do some handling...
}
}
}).start();
// Wait 5 seconds then stop the thread by making the flag false.
Thread.sleep(5000);
stop = true;
}
你的flag显然是process提供的。要点是使用 non-blocking 操作(查看是否确实有要打印的内容)而不是使用阻塞操作。
您应该将读取进程输出流的代码放到一个单独的线程中,并在您的主循环中等待进程以短暂的超时结束,这样您就可以检查是否已取消。
所以主要代码应该是这样的:
Process process = new ProcessBuilder(args).start();
// Read standard output
new StreamConsumer(process.getInputStream()).start();
// You should also always read stderr
new StreamConsumer(process.getErrorStream()).start();
// Wait for process to end and check for cancel
while (!process.waitFor(100, TimeUnit.MILLISECONDS) {
if (monitor.isCanceled() {
// user canceled the job, destroy the process to return
process.destroy();
break;
}
}
而 StreamConsumer
类似于:
public class StreamConsumer extends Thread
{
private final InputStream _input;
public StreamConsumer(final InputStream inputStream)
{
super();
_input = inputStream;
setDaemon(true);
}
@Override
public void run()
{
// TODO your code to read the stream
}
}
就我而言,我不知道这个过程要进行多长时间。所以超时是没有选择的。
我的替代解决方案是启动一个单独的监视线程来监视 IProgressMonitor
的状态。如果进度监视器处于取消状态,则正在执行的线程将被中断。
public static void startMonitorThread(IProgressMonitor monitor) {
final Thread runThread = Thread.currentThread();
new Thread("Monitor") {
@Override
public void run() {
while (runThread.isAlive() && !monitor.isCanceled()) {
try {
Thread.sleep(100);
} catch (InterruptedException exception) {
break;
}
}
if (runThread.isAlive()) {
runThread.interrupt();
}
};
}.start();
}
下一个片段展示了一个如何使用它的例子:
startMonitorThread(monitor);
final Process process = new ProcessBuilder("...").start();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
while (process.isAlive()) {
if (reader.ready()) {
final String line = reader.readLine();
// ... do something with line
} else {
Thread.sleep(10);
}
}
}
首先,我犯了同样的错误,使用了阻塞的扫描器(并且中断没有起作用)。就像 Ben 的回答提到最好使用 BufferedReader
和非阻塞 ready()
方法来检查是否还有更多内容要阅读。
我 运行 在 eclipse 插件中 Job
一个执行长操作而没有太多输出的进程。
如果用户请求,我希望能够取消 Job
,但是通过下面的实现,Job
不会停止,除非进程将某些内容打印到输出流。
Process process = new ProcessBuilder(args).start();
Scanner scanner = new Scanner(
(new InputStreamReader(
process.getInputStream(), UTF_8_CHARSET)));
while (scanner.hasNext())
{
if (monitor.isCanceled() {
// user canceled the job, destroy the process to return
process.destroy();
break;
}
CONSOLE.getStream().println(scanner.nextLine());
}
try {
process.waitFor();
} catch (InterruptedException e) {
Activator.log(ERROR, e.getMessage(), e);
} finally {
process.destroyForcibly();
}
我是否有其他选项来处理作业的取消并更快地停止进程而不是等待新的换行?
而不是 Scanner
使用 BufferedReader
提供 ready
方法,这是一种 non-blocking 告诉你是否有东西要阅读而不是使用的方法扫描器的 nextLine()
在实际读取某些内容之前一直处于阻塞状态。
小示例实现:
volatile static boolean stop = false;
public static void main(String[] args) throws InterruptedException
{
// Create a new thread that reads input from System.in
new Thread(() -> {
BufferedReader read = new BufferedReader(new InputStreamReader(System.in));
while (!stop)
{
try
{
// If there is something to read read it and print it
if (read.ready())
{
System.out.println(read.readLine());
}
}
catch (IOException e)
{
// Do some handling...
}
}
}).start();
// Wait 5 seconds then stop the thread by making the flag false.
Thread.sleep(5000);
stop = true;
}
你的flag显然是process提供的。要点是使用 non-blocking 操作(查看是否确实有要打印的内容)而不是使用阻塞操作。
您应该将读取进程输出流的代码放到一个单独的线程中,并在您的主循环中等待进程以短暂的超时结束,这样您就可以检查是否已取消。
所以主要代码应该是这样的:
Process process = new ProcessBuilder(args).start();
// Read standard output
new StreamConsumer(process.getInputStream()).start();
// You should also always read stderr
new StreamConsumer(process.getErrorStream()).start();
// Wait for process to end and check for cancel
while (!process.waitFor(100, TimeUnit.MILLISECONDS) {
if (monitor.isCanceled() {
// user canceled the job, destroy the process to return
process.destroy();
break;
}
}
而 StreamConsumer
类似于:
public class StreamConsumer extends Thread
{
private final InputStream _input;
public StreamConsumer(final InputStream inputStream)
{
super();
_input = inputStream;
setDaemon(true);
}
@Override
public void run()
{
// TODO your code to read the stream
}
}
就我而言,我不知道这个过程要进行多长时间。所以超时是没有选择的。
我的替代解决方案是启动一个单独的监视线程来监视 IProgressMonitor
的状态。如果进度监视器处于取消状态,则正在执行的线程将被中断。
public static void startMonitorThread(IProgressMonitor monitor) {
final Thread runThread = Thread.currentThread();
new Thread("Monitor") {
@Override
public void run() {
while (runThread.isAlive() && !monitor.isCanceled()) {
try {
Thread.sleep(100);
} catch (InterruptedException exception) {
break;
}
}
if (runThread.isAlive()) {
runThread.interrupt();
}
};
}.start();
}
下一个片段展示了一个如何使用它的例子:
startMonitorThread(monitor);
final Process process = new ProcessBuilder("...").start();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
while (process.isAlive()) {
if (reader.ready()) {
final String line = reader.readLine();
// ... do something with line
} else {
Thread.sleep(10);
}
}
}
首先,我犯了同样的错误,使用了阻塞的扫描器(并且中断没有起作用)。就像 Ben 的回答提到最好使用 BufferedReader
和非阻塞 ready()
方法来检查是否还有更多内容要阅读。