Java 中使用 Scanner 和 Thread 的并行字符串识别不起作用

问题描述 投票:0回答:1

对于个人项目,我正在研究一种通过 JOptionPane 识别字符串的方法。现在我的目标是当我将它放入控制台然后关闭 JOptionPane 时也能识别它。为了实现这一目标,我试图实现一个应该并行工作的线程。因此,当 JOptionPane 打开时,控制台也应该能够获取命令并使用扫描仪对它们做出反应。然而它根本不起作用。线程没有与程序并行工作,但它似乎没有反应。

将控制台命令的扫描器放入线程或 JOptionPane 本身并不重要。另外,我首先调用的顺序(线程或扫描仪)根本不重要。结果始终相同,JOptionPane 从未显示,而是程序仅等待控制台的输入。只有在那之后 JOptionPane 才会显示,但那里的所有输入都会被忽略并被控制台中的前一个输入覆盖。

与此同时,我尝试了几种不同的尝试来解决这个问题,但都没有成功。我觉得我在这里错过了一些重要的东西,因为我没有人可以问,所以我希望你能帮助我。由于我没有想法,所以我需要比我更有经验的人的帮助。请帮我解决这个问题。

以下是我迄今为止尝试过的代码示例:

第一次尝试:


import javax.swing.JOptionPane;

public class NameConsole extends Thread {
    
    public String answer = "";
    
    public void run(){
        answer = (String)JOptionPane.showInputDialog(
                        null,
                        "Please chose the reference. \n",
                        "choice of name",
                        JOptionPane.PLAIN_MESSAGE,
                        null,
                        null,
                        "");
     }

}


public class SelectName {
    public static String setManualname() {
        
        try (Scanner sc = new Scanner(System.in)) {

            NameConsole nameconsole = new NameConsole();
            String name = "";
            
            while (sc.nextLine().equals("")) {
                nameconsole.run();
            
                if (!nameconsole.answer.equals(""))
                    name = nameconsole.answer;
                else if (sc.nextLine() != null)
                    name = sc.nextLine();
            }
        }
    }
}

第二次尝试:

package engine.managers.collectors.identifier.nameconsole;

import javax.swing.JOptionPane;

public class NameConsole extends Thread {
    
    public String answer = "";
    
    public void run(){
        answer = (String)JOptionPane.showInputDialog(
                        null,
                        "Please chose the reference. \n",
                        "choice of name",
                        JOptionPane.PLAIN_MESSAGE,
                        null,
                        null,
                        "");
     }

}


public class SelectName {
    public static String setManualname() {
        
        try (Scanner sc = new Scanner(System.in)) {
            String name = sc.nextLine();
            
            NameConsole nameconsole = new NameConsole();
            nameconsole.run();
            
            while (name.equals("")) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            
                if (!nameconsole.answer.equals(""))
                    name = nameconsole.answer;
                else if (name != null)
                    break;
            }
        }
    }
}

第三次尝试:

package engine.managers.collectors.identifier.nameconsole;

import java.util.Scanner;

public class NameConsole extends Thread {
    
    Scanner sc = new Scanner(System.in);
    public String answer = "";
    
    public void run(){
        answer = sc.nextLine();
     }

}


public class SelectName {
    public static String setManualname() {
        
        String name = "";
        String panelline = (String)JOptionPane.showInputDialog(
                        null,
                        "Please chose the reference. \n",
                        "choice of name",
                        JOptionPane.PLAIN_MESSAGE,
                        null,
                        null,
                        "");
        
        NameConsole nameconsole = new NameConsole();
        nameconsole.run();
        
        while (name.equals("")) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        
            if (panelline != null)
                name = panelline;
            else if (!nameconsole.answer.equals(""))
                name = nameconsole.answer;
        }
    }
}
java multithreading console joptionpane
1个回答
0
投票

这是一个我认为可以满足您需求的版本。它的工作原理是通过 CompletableFuture

 在单独的线程中运行 
both 控制台提示符和 GUI 提示符。然后,主线程等待第一个完成并带有值的线程。

请注意,此实现依赖于在第一次响应后关闭公共线程池并退出程序,因为无法取消或中断阻塞的

Scanner.nextLine
调用。这可能不适合较大的程序。其他 Stack Overflow 答案(example)中介绍了此问题的解决方案,但它们比使用 Scanner 更复杂。

此实现的一个关键特征是它不依赖于线程之间共享的可变状态。

import javax.swing.*;
import java.util.Scanner;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ForkJoinPool;

public class SelectName {
    private static String guiPrompt() {
        return JOptionPane.showInputDialog(
                null,
                "Please chose the reference. \n",
                "choice of name",
                JOptionPane.PLAIN_MESSAGE);
    }

    private static String consolePrompt(Scanner sc) {
        var answer = "";
        while (answer.isEmpty()) {
            System.out.print("Please chose the reference: ");
            answer = sc.nextLine();
        }
        return answer;
    }

    public static String promptForName(Scanner sc) {
        return (String) CompletableFuture.anyOf(
                CompletableFuture.supplyAsync(SelectName::guiPrompt),
                CompletableFuture.supplyAsync(() -> consolePrompt(sc))
        ).join();
    }

    public static void main(String[] args) {
        try (Scanner sc = new Scanner(System.in)) {
            System.out.println("\nUser entered: " + promptForName(sc));
            ForkJoinPool.commonPool().shutdownNow();
            System.exit(0);
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.