【问题标题】:Java FX How to 'Stop' Thread Midway and Restart it or destroy itJava FX 如何在中途“停止”线程并重新启动或销毁它
【发布时间】:2018-10-25 08:07:43
【问题描述】:

无法停止线程Midway重启添加节点线程。

这就是我得到的

这就是我需要的每当我按下刷新按钮

时,我都想要这样的东西

清屏重启(例如。A到N按正确顺序)

为什么?所以我可以在刷新之前选择不同的列表。

背景故事 (忽略) 从一个月开始,我正在研究一个关于 JavaFX 的小项目,但这个问题困扰着我。我做了我的研究并试图弄清楚但没有。如果有人引导我走上正确的道路,我真的很感激。请突出显示这个问题,这样其他人就不必浪费太多时间了

我有 JavaFX 控制器

@FXML public FlowPane flow_panel;

MyPlatform mp = new MyPlatform(); // A class that implements Runnable
Thread t;

boolean first_time_click = true; // To check Whether i clicked '1st' time or 'second' time
@FXML
private void Refresh_Btn(ActionEvent event) 
{       
    System.out.println("Refresh btn");

     t = new Thread(mp); //Creating Thread object

    if(first_time_click == true) { first_time_click = false;



        MyPlatform.stop = false; //Thread object.Stop, When false do nothing

        flow_panel.getChildren().clear(); // cleaning screen
        System.out.println("Start Thread");
        t.setDaemon(true);  
        t.start(); //Start Thread


    } else if(first_time_click == false){   first_time_click = true;



        MyPlatform.stop = true; //Exist loop
        t.interrupt(); // I thought   't.interrupt()'   it work but nothing
        System.out.println("Stop Thread");

        flow_panel.getChildren().clear(); // cleaning screen
        MyPlatform.stop = false; //Thread object.Stop, When false do nothing
        t.setDaemon(true);
        t.start(); //Start Thread
        System.out.println("Stoped  Thread Started again");


    } 

}

然后我有一个名为 MyPlatform 的类,它实现了 Runnable

import javafx.application.Platform;
import javafx.scene.control.Button;
import setups.WindowSetupConfig;

public class MyPlatform implements Runnable
{   

public static boolean stop = false;

@Override
public void run()
{



    for (String name : ListOfNames.getlist()) 
    {
        if(stop)    // Exit for loop if true
        {
            break;
        }
        Platform.runLater(new Runnable()
        {

            @Override
            public void run()
            {   

                Button btn = new Button("Button : "+name);

                System.out.println(name);


        //Adding that button to FlowPane
        WindowSetupConfig.getController().flow_panel.getChildren().add(btn);
                }
            });

            try {
                Thread.sleep(1000); // Wait for 1 sec, Controlling speed
            } catch (InterruptedException e) { // try catch it needed for some reason
                e.printStackTrace();
            }

        }


    }

}

我有一个字符串列表。最初,该列表将包含 500 多个名称

import java.util.ArrayList;

public class ListOfNames
{   
    private static ArrayList<String> list_of_names ;

    public ListOfNames()
    {
        list_of_names = new ArrayList<>();
        list_of_names.add("A");
        list_of_names.add("B");
        list_of_names.add("C");
        list_of_names.add("D");
        list_of_names.add("E");
        list_of_names.add("F");
        list_of_names.add("G");
        list_of_names.add("H");
        list_of_names.add("I");
        list_of_names.add("J");
        list_of_names.add("K");
        list_of_names.add("L");
        list_of_names.add("M");
        list_of_names.add("N");
    }


    public static ArrayList<String> getlist() {
        return list_of_names;
    }
}

每当我按下 刷新按钮我想停止线程中途向流面板添加点头。

使用 flow_panel.getChildren().clear(); 清理 FlowPane; 并从列表的开头重新开始

基本 -停止 -清洁 -重启

如果有任何方法可以通过 Servicetask 做到这一点,那就太好了

【问题讨论】:

  • 请提供一个minimal reproducible example 来说明问题。与您的问题无关:请学习 java 命名约定并遵守它们
  • 基本上,您取消任务,进行清理工作,然后开始新任务 - 或者我错过了什么?
  • @kleopatra 是的,取消任务,清理并重新启动它,完全正确。这就是我无法取消或停止线程的问题
  • 您不能依赖 MyPlatform.stop 的更改值对执行分配的线程以外的线程可见,因为它不是 volatile,因此可以为每个线程创建一个副本。此外,它是static,因此如果您运行多个MyPlatform,所有这些都将被“取消”(假设他们收到消息)。
  • 不是重新开始,创建并开始一个新的..@fabian 所有这些静态访问器无论如何都必须去;)

标签: java multithreading javafx javafx-8 fxml


【解决方案1】:

我没有阅读您的所有代码,但我将简要介绍如何取消和“重新启动”Task

首先,不要使用Threadsuspendstopresume方法;它们被弃用是有原因的。

与所有后台任务一样,取消需要与所述后台任务的开发人员合作。该任务必须在适当的时间检查它是否已被取消并做出相应的反应。一般是通过查询当前Thread的中断状态来实现的,但是Task类继承了FutureTask中更易用的isCancelled方法。

模拟长时间运行的工作示例:

public class MyTask extends Task<Void> {

    @Override
    protected Void call() throws Exception {
        for (int i = 0; i < 10_000; i++) {
            if (isCancelled()) {
                break;
            }
            updateMessage(Integer.toString(i));
            Thread.sleep(1L);
            updateProgress(i, 10_000);
        }
        return null;
    }

}

您可以使用Worker 接口的cancel 方法取消Task。注意循环的每次迭代对isCancelled的检查;当调用cancel 方法时,Task 将尽早停止。此外,调用Worker.cancel()(或Future.cancel(true))将中断Thread,这意味着任何可中断的操作(例如Thread.sleep)都会抛出InterruptedException

您可以通过观察Task 的属性或添加事件处理程序来对Task 成功、失败或取消时做出反应。

MyTask task = new MyTask();
task.setOnSucceeded(event -> handleSucceededTask());
task.setOnFailed(event -> handleFailedTask());
task.setOnCancelled(event -> handleCancelledTask());

您可以在这些回调中进行清理并根据需要执行 new Task。请注意,您必须启动一个新的 Task,因为 Task 是一次性使用的。

【讨论】:

  • 非常感谢非常感谢您的帮助:)
【解决方案2】:

我找到了解决问题的方法。现在我的问题是有没有更好的方法来达到同样的结果 因为我正在和黄色交战,这意味着我做错了方式

Luncher.java

    package project;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class Luncher extends Application
{


    @Override
    public void start(Stage primaryStage) {
        try {


            Parent root = FXMLLoader.load(getClass().getResource("Window.fxml"));

            Scene scene = new Scene(root);          

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

        } catch(Exception e) {
            System.err.println("Luncher Failed !" +e);
        }
    }

    public static void main(String[] args) 
    {

        launch(args);

    }

}

Controller.java

package project;


import java.net.URL;
import java.util.ResourceBundle;

import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.layout.FlowPane;


public class Controller implements Initializable
{


    @FXML
    public FlowPane flowPane;


    //A class that implements  Runable, So i can start a thead there
    private MyRunableClass my_run_class; 
    private Thread t; //Thread object

    @Override
    public void initialize(URL location, ResourceBundle resources)
    {       
        new ListOfNames(); //Init list of names and creating Array list, In real program i will get this list from database
        my_run_class = new MyRunableClass(this);

    }





    @FXML
    void clear_Button(ActionEvent event) 
    {
        flowPane.getChildren().clear(); 
    }


    @FXML
    void start_Button(ActionEvent event) 
    {   
        t = new Thread(my_run_class);
        t.start();
    }

    @FXML
    void stop_Button(ActionEvent event) {
        t.suspend(); ///NOT WORKING???????? any way to stop running thread
    }




    private boolean firstTime_thread_running = true; // To check Whether i clicked '1st' time or 'second' time

    @FXML
    void refresh_Button(ActionEvent event) 
    {


        if(firstTime_thread_running == false){


            //Stop
            //  my_run_class.stop = true; //Exist loop
            t.suspend();
            System.out.println("Suspend");

        } else
        {   
            firstTime_thread_running = false;
        }



//Clean
            flowPane.getChildren().clear(); // cleaning screen
            System.out.println("Screen clear");


//Restart , well.. at least that what i want
            t = new Thread(my_run_class);
            t.setDaemon(true);
            t.start(); //Start Thread
            System.out.println("Stoped  Thread Started again"); 

    }



}

MyRunableClass.java

    package project;

import javafx.application.Platform;
import javafx.scene.control.Button;

public class MyRunableClass implements Runnable
{       
    private Controller controller;

    public MyRunableClass(Controller controller)
    {   
        //Getting FXML Controller
        this.controller = controller;
    }

//  public boolean stop = false;

    @Override
    public void run()
    {



        for (String name : ListOfNames.getlist()) 
        {
//          if(stop)    // Exit for loop if true
//          {
//              break;
//          }
            Platform.runLater(new Runnable()
            {

                @Override
                public void run()
                {   

                    Button btn = new Button("Button : "+name);

                    System.out.println(name);

                    controller.flowPane.getChildren().add(btn);
                }
            });

            try {
                Thread.sleep(1); // Wait for half sec this time
            } catch (InterruptedException e) { // try catch it needed for some reason
                e.printStackTrace();
            }

        }


    }

}

ListOfNames.java

    package project;

import java.util.ArrayList;

public class ListOfNames
{   
    private static ArrayList<String> list_of_names ;

    public ListOfNames()
    {
        list_of_names = new ArrayList<>();
        list_of_names.add("A");
        list_of_names.add("B");
        list_of_names.add("C");
        list_of_names.add("D");
        list_of_names.add("E");
        list_of_names.add("F");
        list_of_names.add("G");
        list_of_names.add("H");
        list_of_names.add("I");
        list_of_names.add("J");
        list_of_names.add("K");
        list_of_names.add("L");
        list_of_names.add("M");
        list_of_names.add("N");
        list_of_names.add("O");
        list_of_names.add("P");
        list_of_names.add("Q");
        list_of_names.add("R");
        list_of_names.add("S");
        list_of_names.add("T");
        list_of_names.add("U");
        list_of_names.add("V");
        list_of_names.add("W");
        list_of_names.add("X");
        list_of_names.add("Y");
        list_of_names.add("Z");

    }


    public static ArrayList<String> getlist() {
        return list_of_names;
    }
}

Window.fxml

    <?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.FlowPane?>


<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="413.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="project.Controller">
   <children>
      <FlowPane fx:id="flowPane" layoutX="2.0" layoutY="61.0" prefHeight="352.0" prefWidth="600.0" style="-fx-border-color: #000000; -fx-border-insets: 1.1; -fx-border-width: 5;" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="61.0" />
      <Button layoutX="405.0" layoutY="14.0" mnemonicParsing="false" onAction="#stop_Button" prefHeight="39.0" prefWidth="80.0" text="Stop" />
      <Button layoutX="313.0" layoutY="14.0" mnemonicParsing="false" onAction="#start_Button" prefHeight="39.0" prefWidth="80.0" text="Star" />
      <Button layoutX="497.0" layoutY="14.0" mnemonicParsing="false" onAction="#clear_Button" prefHeight="39.0" prefWidth="80.0" text="Clean" />
      <Button layoutX="40.0" layoutY="14.0" mnemonicParsing="false" onAction="#refresh_Button" prefHeight="39.0" prefWidth="109.0" text="Refresh" />
   </children>
</AnchorPane>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-12-25
    • 1970-01-01
    • 1970-01-01
    • 2012-11-11
    • 2011-01-08
    • 2012-11-28
    • 1970-01-01
    相关资源
    最近更新 更多