java - Как принимать ввод с консоли и при этом не усыпляя другие потоки

Мне надо ожидать вывод с консоли в одном потоке и обновлять окно в другом.

Java 21

Пример кода:

package com.example.test;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import java.util.Timer;
import java.util.TimerTask;

public class MainFile extends Application {
    public static boolean ExitUpdate = false;
    public static Label label = new Label("Hello, JavaFX!");

    @Override
    public void start(Stage primaryStage) {
        // Создаем JavaFX окно
        StackPane root = new StackPane();
        root.getChildren().add(label);
        Scene scene = new Scene(root, 300, 200);
        primaryStage.setScene(scene);
        primaryStage.show();
        update(root, 0);
    }
    public void update(StackPane root, int c) {
        if (c > 1) {
            c = 0;
        }
        switch (c) {
            case 0:
                root.getChildren().addAll(new Rectangle(100,100, Color.BLUE));
                break;
            case 1:
                root.getChildren().addAll(new Rectangle(110,110, Color.RED));
                break;
            default:
                System.out.println("err");
        }

        int sendc = c+1;
        TimerTask timerTask = new TimerTask() {
            public void run() {
                Platform.runLater(new Runnable() {
                    @Override
                    public void run() {
                        update(root, sendc);
                    }
                });
            }
        };
        Timer start = new Timer("test");
        start.schedule(timerTask, 1000L);
    }


    public static void main (String[] args) {
        launch(args);
    }
}

К примеру как тут сделать ожидание ввода, чтобы квадраты не переставали появляться раз в секунду.

Если это невозможно, то какую альтернативу можно использовать?


Ответы (1 шт):

Автор решения: TaranenkoAnt

Можно сделать с помощью ExecutorService, внутри него отправлять сообщение в Fx-поток через Platform.runLater()

import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;

import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class MainFile extends Application {


    private static Label label = new Label("Hello, JavaFX!");

    private  final ExecutorService executor = Executors.newSingleThreadExecutor();

@Override
public void start(Stage primaryStage) {
    StackPane root = new StackPane();
    root.getChildren().add(label);
    Scene scene = new Scene(root, 300, 200);
    primaryStage.setScene(scene);
    primaryStage.show();

    executor.submit(() -> {
        Scanner scanner = new Scanner(System.in);
        while (true) {
            System.out.println("Press Enter to continue...");
            String s = scanner.nextLine();
            if(s != null && !s.trim().isEmpty() && s.matches("[0-9]+")) {
                Platform.runLater(() -> update(root, Integer.parseInt(s)));
            }
        }
    });

    update(root, 0);
}

public void update(StackPane root, int c) {
    if (c > 1) {
        c = 0;
    }

    switch (c) {
        case 0:
            root.getChildren().addAll(new Rectangle(100, 100, Color.BLUE));
            break;
        case 1:
            root.getChildren().addAll(new Rectangle(110, 110, Color.RED));
            break;
        default:
            System.out.println("err");
    }

    int sendc = c + 1;
    executor.submit(() -> update(root, sendc));
}

public static void main(String[] args) {
    launch(args);
}

}

→ Ссылка