当前位置: 首页 > 面试题库 >

为什么线程会阻塞我的JavaFX UI线程?

张银龙
2023-03-14
问题内容

当用户选择在另一个线程中启动阻止进程的菜单项时,我试图在JavaFX
8应用程序中提供反馈。在我的实际应用程序中,它是文件下载,但是通过示例,我使用最少的代码创建了一个测试用例:

import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.control.MenuButton;
import javafx.scene.control.ToolBar;
import javafx.scene.control.MenuItem;
import javafx.stage.Stage;

public class BlockingThreadTestCase extends Application {
    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        MenuItem menuItem = new MenuItem("Start");
        MenuButton menuButton = new MenuButton();
        menuButton.setText("Async Process");
        menuButton.getItems().addAll(menuItem);

        menuItem.setOnAction(event -> {
            menuButton.setText("Running...");

            Platform.runLater(() -> {
                try {
                    // Simulate a blocking process
                    Thread.sleep(5000);
                } catch (Exception e) {
                    e.printStackTrace();
                }

                menuButton.setText(menuButton.getText() + "Done!");
            });
        });

        final ToolBar toolbar = new ToolBar(menuButton);
        final Scene scene = new Scene(toolbar);
        primaryStage.setScene(scene);
        primaryStage.setWidth(150);
        primaryStage.show();
    }
}

它的工作方式如下:当选择“开始”菜单项时,主菜单文本应立即更改为“正在运行…”,然后应附加“完成!”。经过5秒钟的模拟我的文件下载的睡眠。

实际上发生的是,即使我正在使用,在阻止过程完成 两个 文本更新也会触发。我究竟做错了什么? __Platform.runLater()


问题答案:

最简单的方法是使用TaskPlatform.runLater仅当您需要从其他线程更新UI时才需要,因此在您的情况下则不需要。如果要在后台任务运行时跟踪其进度,可以在任务中使用updateMessageupdateProgress方法将消息安全地传递到UI线程,而不必担心通过EDT进行调度。您可以在这里https://docs.oracle.com/javase/8/javafx/interoperability-
tutorial/concurrency.htm
上找到更多信息。

请参阅下面的最小工作示例

import javafx.application.Application;
import javafx.concurrent.Task;
import javafx.scene.Scene;
import javafx.scene.control.MenuButton;
import javafx.scene.control.MenuItem;
import javafx.scene.control.ToolBar;
import javafx.stage.Stage;


public class BlockingThreadTestCase extends Application {
    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        MenuItem menuItem = new MenuItem("Start");
        MenuButton menuButton = new MenuButton();
        menuButton.setText("Async Process");
        menuButton.getItems().addAll(menuItem);

        menuItem.setOnAction(event -> {
            menuButton.setText("Running...");

            Task task = new Task<Void>() {
                @Override
                public Void call() {
                    //SIMULATE A FILE DOWNLOAD
                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    return null;
                }
            };
            task.setOnSucceeded(taskFinishEvent -> menuButton.setText(menuButton.getText() + "Done!"));
            new Thread(task).start();
        });

        final ToolBar toolbar = new ToolBar(menuButton);
        final Scene scene = new Scene(toolbar);
        primaryStage.setScene(scene);
        primaryStage.setWidth(150);
        primaryStage.show();
    }
}


 类似资料:
  • 我不明白为什么webclient会阻止我使用gradle的主要netty线程,以下是它的依赖项: 这个gradle脚本在两个应用程序中都使用。在第一个应用程序中,我执行: 第二个应用程序模拟长响应处理: 我希望呼叫服务不会阻塞主线程,而是会继续处理传入的连接,但直到我收到第一个呼叫的响应(睡眠将起作用),我的下一个连接将挂起等待。 结果:第一个应用程序像tomcat一样工作,只有一个线程 我的问题

  • 我不明白以下几点: 用户级线程需要非阻塞系统调用,即多线程内核。否则,整个进程将在内核中阻塞,即使进程中还有可运行的线程。 内核线程如何处理阻塞系统调用?在用户级线程中,当一个线程进行阻塞系统调用(例如读取)时,为什么其他线程不能继续工作?

  • 线程实例的join()方法可用于将一个线程的执行开始“连接”到另一个线程的执行结束,这样一个线程在另一个线程结束之前不会开始运行。如果对线程实例调用join(),则当前运行的线程将阻塞,直到线程实例完成执行 但是如果我有多个线程并且当我在循环内部调用join时。所有线程并行运行。但是根据连接的概念,首先连接的线程应该完成,然后只有主线程才允许连接其他线程。 } 在上面的代码中,如果第一个线程被连接

  • 这是一个扩展Thread并实现run()函数的类: 现在在主活动中的一个按钮中,我有这样的代码: 据我所知,这应该将runnable放在目标线程的消息队列中,并且线程(不是UI线程)将在可能的情况下运行它。但此代码会阻止 UI。为什么会发生这种情况?如您所见,我将目标线程的循环器发送到处理程序构造函数,并且处理程序应使用该循环器而不是主线程的循环程序。

  • 问题内容: 更新: 这看起来像是内存问题。一个3.8 Gb Hprof文件表明,发生此“阻塞”时,JVM正在对其堆进行转储。我们的运营团队发现该站点没有响应,进行了堆栈跟踪,然后关闭了实例。我相信他们在堆转储完成之前就关闭了该站点。日志中 没有 错误/异常/问题证据-可能是因为JVM在生成错误消息之前就被杀死了。 最初的问题我们最近遇到了一种情况,该应用程序对最终用户似乎挂起了。在应用程序重新启动

  • 我有4-5个工作线程处理大型消息队列。我还有另一段代码,它使用2-3个worker运行。我想在处理大型消息队列时阻止所有其他工作者。 我正在使用JDK6和Jms 编辑: 队列进程工作者从未终止。当没有消息时,它们阻塞队列。这些工作者由执行器线程池管理,如果我使用读写锁,其中一个工作者也会被阻塞。此外,如果使用循环屏障,那么我必须终止线程,以便重新传递阻塞的第二个进程。由于工作者是由线程池管理的,所