通过外部切换标志来运行线程(来自GUI)

时间:2018-01-02 11:02:57

标签: java multithreading javafx

我正在制作一个简单的JavaFX大学课程项目,我需要一种处理线程的好方法,主要是在激活某个标志时运行它们。

这是我提出的简单草图:

public class ListenerService extends Thread {

    private static ArrayList<ListenerService> listeners = new ArrayList<>();

    private ToggleButton button;
    private File folder;
    private SimpleBooleanProperty active = new SimpleBooleanProperty();

    ListenerService(ToggleButton button, String pathname) {
        this.button = button;
        this.folder = new File(pathname);

        button.setOnAction(event -> active.set(button.isSelected()));
        active.addListener((ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue)
                            -> {if (newValue.booleanValue()) start();});

        listeners.add(this);
    }

    @Override
    public void run() {
        while(active.get())
            System.out.print(".");
    }

流程如下:

  1. 用户在表单上动态创建ToggleButton。一个 创建ListenerService对象,其中包含一个按钮和一个目录 被分配。

  2. 为按钮分配了一个监听器 - 如果它被点击 - 激活     国旗。否则,停用。这里的旗帜是     SimpleBooleanProperty实例。

  3. 如果标志已打开,请运行该线程。该线程将运行 旗帜是活跃的。如果用户再次切换按钮 停用它,while循环中的条件将失败 线程应该停止运行。
  4. 一旦我运行该程序,它就冻结了。我试着让旗帜变得不稳定,但没有改变。由于标志是从外部控制的(从GUI),因此无法使此方法同步。

    我做错了什么?

2 个答案:

答案 0 :(得分:0)

您基本上创建了一个新的线程,只要选择了该按钮就会运行,并在未选择该按钮时退出。

import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.scene.Scene;
import javafx.scene.control.ToggleButton;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;


public class ThreadApp extends Application {    

    public class Worker implements Runnable{
        private boolean active;

        public void setActive(boolean active) {
            this.active = active;
        }

        @Override
        public void run() {
            while(active)
            {
                System.out.println("Active! " + System.currentTimeMillis());
            }
        }
    }

    public class WorkerToggle extends ToggleButton {
        Worker worker;

        public WorkerToggle(String text) {
            super(text);
            this.worker = new Worker();

            setOnAction((event) -> {
                if(isSelected())
                {
                    worker.setActive(true);
                    Thread thread = new Thread(worker);
                    thread.setDaemon(true);
                    thread.start();
                }else
                {
                    worker.setActive(false);
                }
            });
        }
    }

    @Override
    public void start(Stage primaryStage) {
        BorderPane rootPane = new BorderPane();
        Scene scene = new Scene(rootPane);

        rootPane.setCenter(new WorkerToggle("toggle me"));

        primaryStage.setScene(scene);
        primaryStage.show();
    }

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

这应该可以正常工作,但是创建线程可能很昂贵,所以如果你发现某些性能问题,你可能需要调查ThreadPoolExecutor

答案 1 :(得分:0)

在JavaFX中,您可以使用计划的服务来运行主FX线程。这是一个可能有用的简单示例。

public class JavaFXApplication3 extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception {
        PollingService service = new PollingService();
        service.setPeriod(Duration.millis(1000)); // sysout every second
        ToggleButton tb = new ToggleButton("Start Process");
        tb.setOnAction(event -> {
            System.out.println(tb.isSelected());
            if(tb.isSelected()){
                service.reset();
                service.start();
            }else {
                service.cancel();
            }
        });

        VBox vbox = new VBox(tb);
        Scene scene = new Scene(vbox);
        primaryStage.setScene(scene);
        primaryStage.show();;

    }

    private class PollingService extends ScheduledService<Void> {
        @Override
        protected Task<Void> createTask() {
            return new Task<Void>() {
                @Override
                protected Void call() {
                    System.out.print(".#.");
                    return null;
                }
            };
        }
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }

}