java 如何停止“JavaFX 应用程序线程”

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15808063/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 20:56:20  来源:igfitidea点击:

how to stop "JavaFX Application Thread"

javajavafx-2javafx

提问by Francesco

I have a simple console application which sometimes need to perform graphics operations, for those I'm using JavaFx framework (there are some functions that I need like the css styling for text ) I simply generate some shapes and text into an hidden scene then save those on file and that's all,

我有一个简单的控制台应用程序,有时需要执行图形操作,对于那些我使用 JavaFx 框架的应用程序(我需要一些功能,例如文本的 css 样式)我只需将一些形状和文本生成到隐藏场景中然后保存档案中的那些,仅此而已,

I know that to work with JavaFx I have to pass graphics operations to the JavaFx thread, but when everything is done and I have to close the application (after some hours) this JavaFx thread still remain open... and I really don't want to force exit with System.exit() because if something is blocked I may want to know/wait (ALSO I don't want to execute everything as an JavaFx application (as JavaFx components are less than 1% of my main application)

我知道要使用 JavaFx,我必须将图形操作传递给 JavaFx 线程,但是当一切都完成并且我必须关闭应用程序时(几个小时后),这个 JavaFx 线程仍然保持打开状态......我真的没有想使用 System.exit() 强制退出,因为如果某些内容被阻止,我可能想知道/等待(另外我不想将所有内容作为 JavaFx 应用程序执行(因为 JavaFx 组件不到我的主应用程序的 1%)

the code is very simple and googling around I've found only to use

代码非常简单,我发现只能使用谷歌搜索

Platform.exit();

which doesn't seems to work, I've also tried playing with Platform parameters like

这似乎不起作用,我也尝试过使用平台参数,例如

Platform.setImplicitExit(false);

here is my test application which you can run :

这是我可以运行的测试应用程序:

import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.geometry.Pos;
import javafx.scene.layout.VBox;

public class SOTestFX {
    public static void main(String[] args) {
        SOTestFX t = new SOTestFX();
        t.runFxThread();
    }

    public  void runFxThread(){
        //Application.launch(args);
        final JFXPanel jfxPanel = new JFXPanel(); 
        Platform.runLater(new Runnable() {
            @Override
            public void run() {

                System.err.println("CREATING IMAGE");
                simpleFXoperations();
                System.err.println("NOW CALL EXIT");
                System.err.println("JAVA FX THREAD SHOULD BE EXITED NOW");
                Platform.exit();
            }
        });

        try {
            Thread.sleep(3000); // just wait a bit if something should happen, let it happen..
        } catch (InterruptedException e) {
            e.printStackTrace();  
        }
        //jfxPanel.removeNotify(); // return ->  java.lang.NullPointerException
        //Platform.exit(); // -> does nothing

        System.err.println("i will never die!");
    }
    public void simpleFXoperations(){

        VBox vbox1 = new VBox();
        vbox1.setAlignment(Pos.BOTTOM_CENTER);
        vbox1.setStyle("-fx-border-style: solid;"
                + "-fx-border-width: 1;"
                + "-fx-border-color: white");
        System.err.println("simpleFXoperations() _DONE");
    }
}

and this is the thread which never close

这是永远不会关闭的线程

"Attach Listener" - Thread t@17 java.lang.Thread.State: RUNNABLE

Locked ownable synchronizers: - None

"JavaFX Application Thread" - Thread t@13 java.lang.Thread.State: RUNNABLE at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method) at com.sun.glass.ui.gtk.GtkApplication$3$1.run(GtkApplication.java:82) at java.lang.Thread.run(Thread.java:722)

Locked ownable synchronizers: - None

“附加侦听器” - 线程 t@17 java.lang.Thread.State: RUNNABLE

锁定的可拥有同步器: - 无

“JavaFX 应用程序线程” - 线程 t@13 java.lang.Thread.State: RUNNABLE at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method) at com.sun.glass.ui.gtk.GtkApplication$3 $1.run(GtkApplication.java:82) 在 java.lang.Thread.run(Thread.java:722)

锁定的可拥有同步器: - 无

Update:I'm using latest Oracle JDK 7u17 64bit on Linux Fedora 16 64bit.

更新:我在 Linux Fedora 16 64 位上使用最新的 Oracle JDK 7u17 64 位。

回答by durron597

Fix:

使固定:

I was able to fix this problem by calling com.sun.javafx.application.PlatformImpl.tkExit()immediately before Platform.exit(). I don't really understand the JavaFX source that well, but it seems to be working; YMMV.

我能够通过com.sun.javafx.application.PlatformImpl.tkExit()Platform.exit(). 我不太了解 JavaFX 源代码,但它似乎有效;天啊。

Update:Doing this in Java 8 will produce a warning, you can just turn the warning off with @SuppressWarnings("restriction"). It shouldn't be a problem.

更新:在 Java 8 中执行此操作会产生警告,您可以使用@SuppressWarnings("restriction"). 这应该不是问题。

Explanation:

解释:

I figured this out by digging through the source code; JFXPanelhas this little snippet (this is from JavaFX 2.2.25)

我通过挖掘源代码发现了这一点;JFXPanel有这个小片段(这是来自 JavaFX 2.2.25)

finishListener = new PlatformImpl.FinishListener() {
  public void idle(boolean paramAnonymousBoolean) {
    if (!JFXPanel.firstPanelShown) {
      return;
    }
    PlatformImpl.removeListener(JFXPanel.finishListener);
    JFXPanel.access2(null);
    if (paramAnonymousBoolean)
      Platform.exit();
  }

  public void exitCalled()
  {
  }

The problem is, if you are using only a little bit of JavaFX in your application, then the idle(boolean)method never does anything (because firstPanelShown == false), which prevents the listener from getting removed, which prevents the JavaFX Toolkitfrom shutting down... which means you have to shut it down manually.

问题是,如果您在应用程序中只使用了一点点 JavaFX,那么该idle(boolean)方法从不执行任何操作(因为firstPanelShown == false),这会阻止侦听器被删除,从而阻止 JavaFXToolkit关闭……这意味着您有手动关闭它。

回答by LeonidVlad

Your main function does not belong to the JavaFx Application object and i think that your program never eneter application thread loop.

您的 main 函数不属于 JavaFx Application 对象,我认为您的程序永远不会进入应用程序线程循环。

It seems you should do:

看来你应该这样做:

public class SOTestFX extends Application {
    public static void main(String[] args) {
        launch(args);
    }
    @Override
    public void start(Stage stage) throws Exception {
        // Do stuff here to show your stage or whatever you want;
        // This will be called on the JavaFX thread
    }
}

回答by Michael Oberlin

That's a slippery situation, as (to my understanding) the purpose of the JavaFX thread is to take advantage of various hardware pipelines transparently. Might I suggest placing your JavaFX requests in a separate, referenced, project; and keep everything else, including your main method, in another? That's always worked for me.

这是一个棘手的情况,因为(据我所知)JavaFX 线程的目的是透明地利用各种硬件管道。我是否建议将您的 JavaFX 请求放在一个单独的、引用的项目中;并将其他所有内容(包括您的主要方法)保存在另一个中?那总是对我有用。

Basically, business logic and model go in one project, and view and control (generally JavaFX-based) go in the other. This allows for independent termination of the JavaFX thread. Hopefully that is applicable to what you are trying to do.

基本上,业务逻辑和模型在一个项目中,视图和控制(通常基于 JavaFX)在另一个项目中。这允许独立终止 JavaFX 线程。希望这适用于您正在尝试做的事情。

回答by Wingie

I tried a lot of things on this as none of the above answers worked for me. Best thing for me was to just shutdown the whole JVM using

我在这方面尝试了很多事情,因为上述答案都不适合我。对我来说最好的事情就是关闭整个 JVM 使用

System.exit(1);

as my whole Application is just that one JavaFX application and therefor can be shut down, when closing the Stage. The 1 in my case is just a random int.

因为我的整个应用程序只是一个 JavaFX 应用程序,因此可以在关闭舞台时关闭。在我的例子中 1 只是一个随机整数。