gpt4 book ai didi

java - 当多个线程在 Java 中的 System.in 上使用扫描程序时,stdin 数据会发生什么变化?

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:15:37 25 4
gpt4 key购买 nike

假设我有一个主程序,它监听标准输入上的命令行参数。这个主程序生成一个线程来做一些事情,线程还需要监听标准输入。

如果两个不同的线程在 System.in 上有扫描器,一个会阻塞另一个,还是两个线程都从 stdin 接收到所有数据?

最佳答案

我尝试了这段代码(在 main 方法中):

Scanner scan = new Scanner(System.in);
new Thread(){
public void run(){
Scanner scan = new Scanner(System.in);
while(true){
if(scan.hasNext())System.out.println("Thread:"+scan.nextLine());
}
}
}.start();
while(true){
if(scan.hasNext())System.out.println("Main:"+scan.nextLine());
}

大多数时候,两个线程都没有打印,当它打印时,很明显它们都在同时解析输入。虽然它们(我认为)并没有以重复字符结束,但 abcd 的输入可能会将 ac 发送到一个线程的扫描器,并将 bd 发送到线程的扫描器另一个。

示例运行(输入任何未以 Main:Thread: 开头的内容):

abcdefghi
jklmnopqr
Thread:ghi
Thread:mnopqr
stuvwxyzA
Thread:vwxyzA
BCDEFGHIJ
KLMNOPQRS
Thread:KLM
Main:abcdefjklstuBCDEFGHIJ
TUVWXYZ`~
1!2@3#4$5
Main:NOPQRS~
Thread:TUVWXYZ`1!2@3#4$5

如果您希望两个线程都获得标准输入,您可以创建一个这样的类(它可以工作,但根本不是最佳选择):

class STDIN extends Thread{ //this way, it can only be used once, like intended.
private static final BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
private static final ArrayList<Integer> data = new ArrayList<>();
private static final ArrayList<Integer> dataFlags = new ArrayList<>();

public void run(){
while(true){
synchronized(data){
try {
int i = stdin.read();
if (i == -1) break;
data.add(i);
} catch (IOException ex) {
ex.printStackTrace();
}
synchronized(dataFlags){
if (dataFlags.get(0) == 3){
dataFlags.remove(0);
data.remove(0);
}
}
}
}
try {
stdin.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
public int getByte(int index){
synchronized(data){
return data.get(index);
}
}
public void flagA(int index){
synchronized(dataFlags){
if (index>dataFlags.size()){
dataFlags.add(1);
}
else{
dataFlags.set(index, dataFlags.get(index) | 1);
}
}
}
public void flagB(int index){
synchronized(dataFlags){
if (index>dataFlags.size()){
dataFlags.add(2);
}
else{
dataFlags.set(index, dataFlags.get(index) | 2);
}
}
}
}

使用它,您可以读取数据,但一次只能读取一个字符。当您完成数据处理后,您可以根据您所在的线程对其进行标记。 (flagA 用于一个线程,flagB 用于另一个线程)。

这是 Scanner 的部分包装器;我只包含 nextLine 方法:

class MultithreadedScanner {
private final Scanner scan;
private final ArrayList<MultithreadedScannerListener> toNotify;

public MultithreadedScanner(InputStream is) {
scan = new Scanner(is);
toNotify = new ArrayList<>();
}

public void addMultithreadedScannerListener(MultithreadedScannerListener l) {
synchronized (toNotify) {
toNotify.add(l);
}
}

public void nextLine() {
String s = scan.nextLine();
synchronized(toNotify){
for (MultithreadedScannerListener l: toNotify){
l.receiveNextLine(s);
}
}
}
}

interface MultithreadedScannerListener {
public void receiveNextLine(String line);
}

在实现 MultithreadedScannerListener 时让您想要监听的每个线程都成为标准输入,并将它们添加到 MultithreadedScanner 中。每当需要新信息时调用 nextLine;建议仅从一个线程执行此操作。

关于java - 当多个线程在 Java 中的 System.in 上使用扫描程序时,stdin 数据会发生什么变化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21227328/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com