JavaFX:控制台登录 TextArea + 多线程和任务

标签 java multithreading javafx console task

我正在尝试实现 StackOverflow 上许多人尝试过的盛宴:在基于 JavaFX 构建的 TextArea 中显示 Java 应用程序的控制台输出。
我已经设法在上述 TextArea 中显示我的输出,但与其他许多人一样,我的 UI 卡住了,因为该线程正在大量加载用于显示 UI 本身的线程。

所以我开始阅读有关 Platform.runLater() 的内容,但它并没有解决我的问题,主要是因为我输出了大量文本,这会减慢所述函数的速度。环顾四周,我进入了this question ,其中提出了一个基于 Task 的很好的解决方案。尽管如此,当我开始在 TextArea 中显示控制台日志时,我的 UI 就一直卡住。我将向您展示我的代码片段,以便您能够告诉我我遗漏了什么和/或做错了什么。

这是我的 JavaFX Controller 的片段:

public class MainViewController extends AbstractController implements Initializable {

    @FXML private TextArea textAreaLog;

    @Override
    public void initialize(URL location, ResourceBundle resources) {

        Task<Void> task = new Task<Void>() {
            @Override
            protected Void call() throws Exception {
                boolean fxApplicationThread = Platform.isFxApplicationThread();
                System.out.println("Is call on FXApplicationThread: " + fxApplicationThread);

                Console console = new Console(textAreaLog);
                PrintStream ps = new PrintStream(console, true);
                System.setOut(ps);
                System.setErr(ps);

                return null;
            }

            @Override
            protected void succeeded() {
                boolean fxApplicationThread = Platform.isFxApplicationThread();
                System.out.println("Is call on FXApplicationThread: " + fxApplicationThread);
                super.succeeded();
                textAreaLog.textProperty().unbind();
            }
        };

        textAreaLog.textProperty().bind(task.messageProperty());
        new Thread(task).start();

    }

    // Console Class
    public static class Console extends OutputStream {

        private TextArea output;

        Console(TextArea ta) {
            this.output = ta;
        }

        @Override
        public void write(int i) throws IOException {
            output.appendText(String.valueOf((char) i));
        }

    }

}

我已经编辑了从我之前链接的问题的答案中获取的代码,留下所有调试消息只是为了帮助我。

仅此而已。我的 UI 只是卡住,即使我显然是在后台运行重负载任务,而不是直接在 UI 线程中执行该操作。

最佳答案

我认为问题的根源在于以下之一;

  • System.out.println("text") 是一个同步方法。
  • 在 Ui 线程之外访问 ui 组件

当您从 ui 线程调用 System.out.println("text") 时,System.out 上的同步将导致 UI 在同步期间卡住。 您可以检查这是否是原因,如下所示;(您必须像下面这样包装所有 System.out 调用,只是为了测试上述理论是否正确)
这将导致 println 方法在不同线程中同步。(公共(public)池线程)

CompletableFuture.runAsync(()->System.out.println("text"));

您还应该更新 ui 线程中的输出组件。(在这种情况下问题已解决)

    // or create new runnable if you are not using java8
    Platform.runLater(()->output.appendText(String.valueOf((char) i))); 

关于JavaFX:控制台登录 TextArea + 多线程和任务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48889125/

相关文章:

java - 我需要从选择查询中返回所有值的方法

c++ - QCoreApplication 事件循环和 Windows 服务控制处理函数

multithreading - 服务器上 CPU 密集型和 IO 密集型进程的多进程与多线程

java - 如何修复 Time4J 库中的 NoSuchMethodError?

java - 如何以编程方式限制下载速度?

java - 当库添加为依赖项时,Spring 初始化不起作用

c# - Entity Framework 不使用更新的连接字符串

gradle - 我正在使用javafx-gradle-plugin,构建失败并显示 “Couldn'找不到Ant-JavaFX-library。如何指定JavaFX位置?

按钮的 Javafx 背景图像不起作用

java - 具有 NFC 功能的 GSM 手机 SIM 卡上的应用程序可连接到 Android 应用程序