Java 澄清何时何地启动和停止新线程
我遵循了一个在线教程,为我的JavaFX应用程序构建了一个启动屏幕。以下是SplashController文件:Java 澄清何时何地启动和停止新线程,java,javafx,Java,Javafx,我遵循了一个在线教程,为我的JavaFX应用程序构建了一个启动屏幕。以下是SplashController文件: package splash; import java.io.IOException; import javafx.application.Platform; import javafx.fxml.FXML; import javafx.fxml.FXMLLoader; import javafx.scene.Scene; import javafx.scene.image.Im
package splash;
import java.io.IOException;
import javafx.application.Platform;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.image.ImageView;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
/**
* SplashController controls the Splash.FXML file. This is the initial software display. After a
* designated amount of time, the MainMenu.FXML is run.
*
*/
public class SplashController {
@FXML
private StackPane splashRoot;
@FXML
private ImageView splashImage;
/**
* Called after all @FXML annotated members have been injected. Starts a new thread "SplashScreen()".
*/
@FXML void initialize() {
new SplashScreen().start(); //Start SplashScreen thread.
}
/**
* Inner class that extends thread. Displays the splash screen for a designated amount of time then loads
* MainMenu.FXML, sets a new stage, and displays the main menu. Hides the splash screen.
*
*/
class SplashScreen extends Thread {
@Override
public void run() {
try {
splashImage.fitWidthProperty().bind( splashRoot.widthProperty() ); // binds the image to the rootPane width.
Thread.sleep( 3000 ); // puts the thread (SplashScreen) to sleep in order to allow the splash to display long enough.
Platform.runLater( new Runnable() { // Forces the main menu scene to load onto the SplashScreen thread when it is available.
@Override
public void run() {
FXMLLoader loader = new FXMLLoader( getClass().getResource( "../mainMenu/MainMenu.FXML" ) ); // Places MainMenu.FXML into the loader.
Stage stage = new Stage(); // Creates a new stage.
try {
stage.setScene( new Scene( loader.load() ) ); // Sets the scene using the root node of the loaded FXML document.
} catch ( IOException e ) {
e.printStackTrace();
}
stage.setResizable(false); // Prevents user from resizing the window.
stage.setTitle( "Test" ); // Sets the stage title.
stage.show(); // Displays the stage.
splashRoot.getScene().getWindow().hide(); // Hides the splash screen and presumably ends the SplashScreen thread.
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
我试图解释我对线程如何工作的理解,希望您能为我澄清以下内容是否正确或回答问题:
1) 如果我从未创建任何扩展thread
的新类,或者创建任何新的Runnable()
对象,那么我可以假设JavaFX项目中的所有内容都在单个JavaFX应用程序线程上运行
2) 当我创建内部类SplashScreen extends Thread
并对其调用start()
时,我是否创建了第二个线程?因此,我有两个线程——常规JavaFX应用程序线程和SplashScreen
线程
3) 然后,当我调用Platform.runLater(new Runnable(){..})
时,它是在JavaFX应用程序线程、SplashScreen线程还是新的第三个线程中设置了新的stage、FXML和控制器
4) 当我调用splashRoot.getScene().getWindow().hide()时,SplashScreen线程是否结束了?还是该线程继续执行由Platform.runLater()
调用的new Runnable()
1) 如果我从未创建任何扩展线程或
创建任何新的Runnable()对象,我可以假设
我的JavaFX项目运行在一个JavaFX应用程序线程上
这是正确的,只要您不调用任何这样做的东西(例如,从其他API)
2) 创建内部类时,SplashScreen扩展线程并调用
开始(),我正在创建第二个线程吗?因此,我有两个问题
线程-常规JavaFX应用程序线程和SplashScreen
螺纹
对。请注意,SplashScreen
在需要处理UI内容时使用Platform.runLater()
3) 当我调用Platform.runLater(newrunnable(){….})时
它在JavaFX应用程序中设置了新的stage、FXML和控制器
线程,SplashScreen线程,还是新的第三个线程
调用Platform.runLater()
的代码位于第二个线程上。Platform.runLater()
中的Runnable
对象是放在JavaFX应用程序线程“队列”中的对象,该线程将在完成其正在做或需要做的任何事情(即渲染UI等)后运行该队列
4) 当我调用splashRoot.getScene().getWindow().hide()时,是否结束
飞溅的丝网?或者,该线程是否继续使用新线程
平台调用的Runnable()。runLater()
它只需关闭承载启动屏幕的窗口。线程结束是因为它是线程必须执行的Runnable
中的最后一行代码。线程结束是因为在将Runnable
放入JavaFX应用程序线程队列之后没有其他事情要做
总结
SplashScreen
在需要处理UI内容时使用Platform.runLater()
3) 当我调用Platform.runLater(newrunnable(){….})时
它在JavaFX应用程序中设置了新的stage、FXML和控制器
线程,SplashScreen线程,还是新的第三个线程
调用Platform.runLater()
的代码位于第二个线程上。Platform.runLater()
中的Runnable
对象是放在JavaFX应用程序线程“队列”中的对象,该线程将在完成其正在做或需要做的任何事情(即渲染UI等)后运行该队列
4) 当我调用splashRoot.getScene().getWindow().hide()时,是否结束
飞溅的丝网?或者,该线程是否继续使用新线程
平台调用的Runnable()。runLater()
它只需关闭承载启动屏幕的窗口。线程结束是因为它是线程必须执行的Runnable
中的最后一行代码。线程结束是因为在将Runnable
放入JavaFX应用程序线程队列之后没有其他事情要做
总结
啊,谢谢你!很好的解释——再澄清一点:为什么在醒来后,它会移回JavaFX应用程序线程?所有对
Platform.runLater()
的调用是否都已排队等待应用程序线程?@DylanRussell在thread.sleep()
之后要做的下一件事是调用Platform.runLater()
,因此整个块都已排队等待应用程序线程。事实上,该线程在将Runnable
添加到队列regardl后立即结束