使用两个线程导致 JavaFX 崩溃
Using two threads causes JavaFX to crash
我需要使用两个线程将两个不同的字符附加到同一个 JavaFX TextArea。我可以让一个工作,但是当我添加第二个线程时,它会因一些非常长的异常而中断。我做错了什么?
我查看了这个问题以寻求指导,它让我在一个线程上工作,但不是两个:
package application;
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.TextArea;
import javafx.scene.layout.BorderPane;
public class Main extends Application {
@Override
public void start(Stage primaryStage) {
try {
BorderPane root = new BorderPane();
TextArea textArea = new TextArea();
textArea.setWrapText(true);
root.setCenter(textArea);
textArea.setText("");
new Thread(() -> PrintChar(textArea, 'a', 100)).start();
new Thread(() -> PrintChar(textArea, 'b', 100)).start();
Scene scene = new Scene(root,400,400);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
private void PrintChar(TextArea textArea, char letter, int numb)
{
for(int i = 0; i < numb; ++i)
{
textArea.appendText(letter + "");
}
}
}
您不需要为此任务使用两个线程。您可以简单地按顺序调用 PrintChar 方法:
PrintChar(textArea, 'a', 100);
PrintChar(textArea, 'b', 100);
使用它会使 textArea 输出看起来像这样,每个输出 100 个:
aaaaaa.....bbbbbb.....
但是,如果您“想要”像这样使用两个线程:
new Thread(() -> PrintChar(textArea, 'a', 100)).start();
new Thread(() -> PrintChar(textArea, 'b', 100)).start();
然后您可以通过使用 Platform.runLater
安排 UI 更改,例如包围与 javafx 组件交互的代码,如下所示:
Platform.runLater(() -> {
textArea.appendText(letter + "");
});
这将导致 textArea 被两个线程混合更改,看起来像这样(如果不采取额外步骤,您将无法控制执行顺序):
bbaaabbbbabbbaaaaa.....
如果你想使用线程,但也使用同步,那么它与完全不使用线程没有真正的区别(至少在你的场景中),但是,你可以这样做:
private synchronized void PrintChar(TextArea textArea, char letter, int numb)
{
for(int i = 0; i < numb; ++i)
{
//We still need to wrap the UI code, because other methods from other threads could still interact with the UI and cause issues
Platform.runLater(() -> {
textArea.appendText(letter + "");
});
}
}
输出看起来像这样,每个顺序 100 个:
aaaaaa.....bbbbbb.....
我需要使用两个线程将两个不同的字符附加到同一个 JavaFX TextArea。我可以让一个工作,但是当我添加第二个线程时,它会因一些非常长的异常而中断。我做错了什么?
我查看了这个问题以寻求指导,它让我在一个线程上工作,但不是两个:
package application;
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.TextArea;
import javafx.scene.layout.BorderPane;
public class Main extends Application {
@Override
public void start(Stage primaryStage) {
try {
BorderPane root = new BorderPane();
TextArea textArea = new TextArea();
textArea.setWrapText(true);
root.setCenter(textArea);
textArea.setText("");
new Thread(() -> PrintChar(textArea, 'a', 100)).start();
new Thread(() -> PrintChar(textArea, 'b', 100)).start();
Scene scene = new Scene(root,400,400);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
private void PrintChar(TextArea textArea, char letter, int numb)
{
for(int i = 0; i < numb; ++i)
{
textArea.appendText(letter + "");
}
}
}
您不需要为此任务使用两个线程。您可以简单地按顺序调用 PrintChar 方法:
PrintChar(textArea, 'a', 100);
PrintChar(textArea, 'b', 100);
使用它会使 textArea 输出看起来像这样,每个输出 100 个:
aaaaaa.....bbbbbb.....
但是,如果您“想要”像这样使用两个线程:
new Thread(() -> PrintChar(textArea, 'a', 100)).start();
new Thread(() -> PrintChar(textArea, 'b', 100)).start();
然后您可以通过使用 Platform.runLater
安排 UI 更改,例如包围与 javafx 组件交互的代码,如下所示:
Platform.runLater(() -> {
textArea.appendText(letter + "");
});
这将导致 textArea 被两个线程混合更改,看起来像这样(如果不采取额外步骤,您将无法控制执行顺序):
bbaaabbbbabbbaaaaa.....
如果你想使用线程,但也使用同步,那么它与完全不使用线程没有真正的区别(至少在你的场景中),但是,你可以这样做:
private synchronized void PrintChar(TextArea textArea, char letter, int numb)
{
for(int i = 0; i < numb; ++i)
{
//We still need to wrap the UI code, because other methods from other threads could still interact with the UI and cause issues
Platform.runLater(() -> {
textArea.appendText(letter + "");
});
}
}
输出看起来像这样,每个顺序 100 个:
aaaaaa.....bbbbbb.....