【问题标题】:UI and background thread in JavaFX. bubble sort visualizationJavaFX 中的 UI 和后台线程。冒泡排序可视化
【发布时间】:2020-05-13 19:42:12
【问题描述】:

这是一个冒泡排序算法可视化代码。我想要交换矩形。但是,我无法做到。当我运行程序时,它会等待一段时间,最多 2 秒,然后所有矩形都在移动,它会持续 1 秒或其他时间。问题是我猜的线程,我该怎么办?

public void bubbleSort(Rectangle[] rectangles) throws InterruptedException {
        int pass = 1;
            for(int j = 0; j < rectangles.length-1; j++) {
                for (int i = 0; i < rectangles.length - 1-j; i++) {
                    int pos = i;
                    if (rectangles[i].getHeight() > rectangles[i + 1].getHeight()) {

                        Runnable task = new Runnable() {
                            @Override
                            public void run() {
                                try {
                                    System.out.println("opıjapısdjapsoıdj");
                                    Platform.runLater(new Runnable() {
                                        @Override
                                        public void run() {
                                            createAnimation(pos, pos + 1);
                                            System.out.println("xxxxxxx");
                                        }
                                    });
                                    Thread.sleep(2000);
                                } catch (InterruptedException exception) {
                                    // nothing
                                }
                            }
                        };
                        new Thread(task).start();

                        Rectangle temp = rectangles[i];
                        rectangles[i] = rectangles[i + 1];
                        rectangles[i + 1] = temp;
                    }
                }
            }
    }

【问题讨论】:

  • 任务之间没有延迟。任务本身有延迟,但该延迟仅对每个任务是本地的。更不用说延迟是您使用 FX 线程(即runLater)安排操作之后。无论如何,为此使用线程可能有点矫枉过正,而且麻烦更多。
  • 将您的排序算法分解为离散(但可重复)的步骤。然后use the animation API to periodically execute算法的下一步。当该步骤完成时,UI 应更新以反映新状态。现在算法暂停,直到执行下一步。这一直持续到算法完成。请参阅event-driven programmingstate pattern
  • 请不要重新发布相同的问题 .. 而是根据需要编辑旧的以包含详细信息(特别是 minimal reproducible example
  • 我会听从@Slaw 的建议。首先,我将创建一个包含每个排序状态的 List 列表。然后我会使用Animation API 中的Timeline 每秒显示不同的状态。
  • 这能回答你的问题吗? Dynamic Bar chart in Java FX

标签: java multithreading sorting javafx visualization


【解决方案1】:

永远不要将长时间运行的代码放在 JavaFX 应用程序线程上,因为这会导致您的 GUI 冻结并变得无响应。

在简单的情况下,你可以使用:

Executors.newSingleThreadExecutor().execute(() -> doComputation());

将工作发布到不同的线程并且:

Platform.runLater(() -> updateDisplay());

将 GUI 更新发布到应用程序线程。

不过,更推荐的解决方案是使用Service

这是一个您可以扩展的类,并提供一个createTask() 方法,然后您可以异步调用并监听响应。

例如:

public class SortService extends Service<int[]> {

    private int[] array;

    public void sortArray(int[] array) {
        this.array = array;
        restart();  // restart() restarts the service regardless of its status
    }

    @Override
    public Task<int[]> createTask() {
        return new Task<int[]> {
            @Override
            protected int[] call() throws Exception {
                // do your sorting and then return the result
                return sortedArray;
            }

        }
    }
}

一旦你设置了这个类,你就可以创建一个实例,设置数组,并监听结果。

SortService service = new SortService();
service.valueProperty().addListener((obs, oldValue, newValue) -> {
    // run on JavaFX Application Thread, safe to update GUI

    System.out.println("Hello from JavaFX Application Thread");
    System.out.println(Arrays.toString(newValue));  
// newValue is our sorted int[] (it is the value you return in your service's createTask())
});
service.sortArray(Arrays.asList(1, 2, 5, 4, 3));  // launch the service

如果你想在你的Service运行期间改变值,在你返回之前,你可以调用updateValue(newValue)(也许你想显示排序的每个阶段而不仅仅是最终输出)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-18
    • 2017-03-11
    • 2019-04-21
    • 2020-01-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多