我正在打開一個 PowerShell 實體并通過 System.in 向它發送命令,我想將輸出收集到一個佇列中,這樣我就可以在不干擾輸入命令的情況下列印結果。但是,佇列沒有在主執行緒上填充,在主執行緒上休眠只能稍微解決問題。我想問題在于不同步佇列,但我不確定如何。
package PWST;
import java.io.PrintWriter;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
public class PWST {
public static void main(String[] args) {
try {
Scanner in = new Scanner(System.in);
System.out.print("\033[H\033[2J > "); // clear console.
String[] tokens = in.nextLine().split(",");
Queue<String> stdout = new LinkedList<>();
Queue<String> stderr = new LinkedList<>();
Process process = Runtime.getRuntime().exec("powershell.exe");
new Thread(new SPQ(process.getInputStream(), stdout)).start();
new Thread(new SPQ(process.getErrorStream(), stderr)).start();
PrintWriter out = new PrintWriter(process.getOutputStream());
for (String token : tokens) // parse commands (will be expanded to continuously ask for input)
out.println(token.strip());
// print powershell output after:
System.out.println(stdout);
System.out.println(stderr);
in.close();
out.close();
process.waitFor();
System.out.println("Shell link closed");
} catch (Exception e) { e.printStackTrace(); }
}
}
package PWST;
import java.io.InputStream;
import java.util.Queue;
class SPQ implements Runnable {
private Queue<String> queue;
private InputStream istrm;
public SPQ(InputStream istrm, Queue<String> queue) {
this.istrm = istrm;
this.queue = queue;
}
public void run() {
try {
final byte[] buffer = new byte[1024];
for (int length = 0; (length = istrm.read(buffer)) != -1; )
queue.add(new String(buffer, 0, length)); // store output in queue
} catch (Exception e) { e.printStackTrace(); }
}
}
uj5u.com熱心網友回復:
至少有兩個問題。
首先,關閉ScannerandPrintWriter也將關閉它們的不死流(在這種情況下Scanner是從標準輸入讀取的)。這是不可取的,因為,首先,您永遠不想關閉 stdin 流,其次,該程序可能尚未完成對流的處理,但更重要的是,我會非常小心關閉不是您自己創建的流,只是說.
第二個問題是,您試圖在SPQ實際有時間處理輸出之前讀取(流的)輸出,例如,如果我調整您的代碼并使用...
import java.io.IOException;
import java.io.InputStream;
import java.util.LinkedList;
import java.util.Queue;
public final class Main {
public static void main(String[] args) throws IOException, InterruptedException {
new Main();
}
public Main() throws IOException, InterruptedException {
ProcessBuilder pb = new ProcessBuilder("bash", "-c", "ls");
pb.redirectErrorStream(true);
System.out.println(">> Start process");
Process p = pb.start();
Queue<String> stdout = new LinkedList<>();
Thread thread = new Thread(new SPQ(p.getInputStream(), stdout));
System.out.println(">> Start thread");
thread.start();
System.out.println(">> Waiting for process to exit");
p.waitFor();
System.out.println("<< Process has exited");
System.out.println(stdout);
}
class SPQ implements Runnable {
private Queue<String> queue;
private InputStream istrm;
public SPQ(InputStream istrm, Queue<String> queue) {
this.istrm = istrm;
this.queue = queue;
}
public void run() {
System.out.println(">> Started reading stream");
try {
final byte[] buffer = new byte[1024];
for (int length = 0; (length = istrm.read(buffer)) != -1;) {
queue.add(new String(buffer, 0, length)); // store output in queue
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("<< Done reading stream");
}
}
}
它會輸出...
>> Start process
>> Start thread
>> Waiting for process to exit
<< Process has exited
>> Started reading stream
[]
<< Done reading stream
如您所見,我已經Queue在執行緒完成處理流之前列印了內容。
如果我在列印thread.join();后添加p.waitFor();...
>> Start process
>> Start thread
>> Waiting for process to exit
>> Started reading stream
<< Done reading stream
<< Process has exited
[contents
of
my
working
directory
which
is
not
very
interesting]
可運行的示例...
import java.io.IOException;
import java.io.InputStream;
import java.util.LinkedList;
import java.util.Queue;
public final class Main {
public static void main(String[] args) throws IOException, InterruptedException {
new Main();
}
public Main() throws IOException, InterruptedException {
ProcessBuilder pb = new ProcessBuilder("bash", "-c", "ls");
pb.redirectErrorStream(true);
System.out.println(">> Start process");
Process p = pb.start();
Queue<String> stdout = new LinkedList<>();
Thread thread = new Thread(new SPQ(p.getInputStream(), stdout));
System.out.println(">> Start thread");
thread.start();
System.out.println(">> Waiting for process to exit");
p.waitFor();
thread.join();
System.out.println("<< Process has exited");
System.out.println(stdout);
}
class SPQ implements Runnable {
private Queue<String> queue;
private InputStream istrm;
public SPQ(InputStream istrm, Queue<String> queue) {
this.istrm = istrm;
this.queue = queue;
}
public void run() {
System.out.println(">> Started reading stream");
try {
final byte[] buffer = new byte[1024];
for (int length = 0; (length = istrm.read(buffer)) != -1;) {
queue.add(new String(buffer, 0, length)); // store output in queue
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("<< Done reading stream");
}
}
}
請注意 - 我沒有運行 Windows,所以我無法測驗Powershell,我已經完成了我能想到的最小示例,所以我沒有將內容寫入流,但從概念上講,這解決了你似乎是的問題有
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/467457.html
下一篇:網路爬蟲的多執行緒或多處理
