使用两个线程会导致JavaFX崩溃

使用两个线程会导致JavaFX崩溃,java,multithreading,javafx,Java,Multithreading,Javafx,我需要使用两个线程将两个不同的字符附加到同一个JavaFXTextArea。我可以让一个线程工作,但当我添加第二个线程时,它会出现一些很长的异常。我做错了什么 我看了这个问题寻求指导,它让我得到了一条线索,但不是两条: 包应用; 导入javafx.application.application; 导入javafx.stage.stage; 导入javafx.scene.scene; 导入javafx.scene.control.TextArea; 导入javafx.scene.layout.B

我需要使用两个线程将两个不同的字符附加到同一个JavaFXTextArea。我可以让一个线程工作,但当我添加第二个线程时,它会出现一些很长的异常。我做错了什么

我看了这个问题寻求指导,它让我得到了一条线索,但不是两条:

包应用;
导入javafx.application.application;
导入javafx.stage.stage;
导入javafx.scene.scene;
导入javafx.scene.control.TextArea;
导入javafx.scene.layout.BorderPane;
公共类主扩展应用程序{
@凌驾
公共无效开始(阶段primaryStage){
试一试{
BorderPane根=新的BorderPane();
TextArea TextArea=新建TextArea();
textArea.setWrapText(true);
root.setCenter(textArea);
textArea.setText(“”);
新线程(()->PrintChar(textArea'a',100)).start();
新线程(()->PrintChar(textArea'b',100)).start();
场景=新场景(根,400400);
scene.getStylesheets().add(getClass().getResource(“application.css”).toExternalForm());
初级阶段。场景(场景);
primaryStage.show();
}捕获(例外e){
e、 printStackTrace();
}
}
公共静态void main(字符串[]args){
发射(args);
}
私有void PrintChar(TextArea TextArea,char letter,int numb)
{
for(int i=0;i
此任务不需要使用两个线程。您只需按以下顺序调用PrintChar方法:

PrintChar(textArea, 'a', 100);
PrintChar(textArea, 'b', 100);
使用此选项将导致textArea输出如下所示,每个输出100个:

aaaaa…..bbbbbb


但是,如果您“想要”使用两个这样的线程:

new Thread(() -> PrintChar(textArea, 'a', 100)).start();
new Thread(() -> PrintChar(textArea, 'b', 100)).start();
Platform.runLater(() -> {
    textArea.appendText(letter + "");
});
然后,您可以通过使用
平台来计划UI更改。例如,runLater
,围绕与javafx组件交互的代码,如下所示:

new Thread(() -> PrintChar(textArea, 'a', 100)).start();
new Thread(() -> PrintChar(textArea, 'b', 100)).start();
Platform.runLater(() -> {
    textArea.appendText(letter + "");
});
这将导致textArea被两个线程的混合更改,并且看起来像这样(如果不采取其他步骤,您无法控制执行顺序):

BBAAABBBBBAAAAA


如果您想使用线程,但也要使用同步,那么它与完全不使用线程(至少在您的场景中)没有什么区别,但是,您可以这样做:

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 + "");
        });
    }
}
private synchronized void PrintChar(TextArea TextArea,char letter,int numb)
{
for(int i=0;i{
textArea.appendText(字母+“”);
});
}
}
输出结果如下所示,每个顺序为100:

PrintChar(textArea, 'a', 100);
PrintChar(textArea, 'b', 100);
aaaaa…..bbbbbb


此任务不需要使用两个线程。您只需按以下顺序调用PrintChar方法:

PrintChar(textArea, 'a', 100);
PrintChar(textArea, 'b', 100);
使用此选项将导致textArea输出如下所示,每个输出100个:

aaaaa…..bbbbbb


但是,如果您“想要”使用两个这样的线程:

new Thread(() -> PrintChar(textArea, 'a', 100)).start();
new Thread(() -> PrintChar(textArea, 'b', 100)).start();
Platform.runLater(() -> {
    textArea.appendText(letter + "");
});
然后,您可以通过使用
平台来计划UI更改。例如,runLater
,围绕与javafx组件交互的代码,如下所示:

new Thread(() -> PrintChar(textArea, 'a', 100)).start();
new Thread(() -> PrintChar(textArea, 'b', 100)).start();
Platform.runLater(() -> {
    textArea.appendText(letter + "");
});
这将导致textArea被两个线程的混合更改,并且看起来像这样(如果不采取其他步骤,您无法控制执行顺序):

BBAAABBBBBAAAAA


如果您想使用线程,但也要使用同步,那么它与完全不使用线程(至少在您的场景中)没有什么区别,但是,您可以这样做:

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 + "");
        });
    }
}
private synchronized void PrintChar(TextArea TextArea,char letter,int numb)
{
for(int i=0;i{
textArea.appendText(字母+“”);
});
}
}
输出结果如下所示,每个顺序为100:

PrintChar(textArea, 'a', 100);
PrintChar(textArea, 'b', 100);
aaaaa…..bbbbbb


UI由单个线程控制,并且不是线程安全的。要从任何其他线程编辑UI,您需要使用
Platform.runLater(()->{textArea.appendText(字母+“”);}),请注意从另一个线程更新UI的代码是如何放置在括号中的。如果不这样做,那么如果不同的线程试图在同一时间与同一事物进行交互,就会出现各种各样的问题。通过使用runLater,更新计划一次进行一次,因为UI线程能够在管理用户交互的同时管理更新。@Sorifind,感谢您的响应。问题是懒惰的老师从不同版本的教科书中分配了这个作业。学生们所学的内容不包括多线程。她发布了她想做的事情,并说用她在20分钟视频中介绍的工具应该是可行的。你所说的一切都没有在视频中介绍:(我查看了另一个线程,但它并没有很好地回答我的问题。同步将如何工作?同步是一个完全不同的主题,在您的场景中并不需要,因为UI线程将正确地管理它。当多个线程访问同一数据,但使用
Pl时,同步很重要atform.runLater
为javafx解决了这个问题。对于与UI无关的代码,它需要一种完全不同的方法,一种方法是小心地使用
volatile
变量和事件队列。我强烈建议遵循官方教程,它提供了一些很好的信息:为什么你认为你需要并发?这很可能是学校作业使用