在Java中,当我在TextArea中使用多线程时,有一个问题

在Java中,当我在TextArea中使用多线程时,有一个问题,java,multithreading,javafx,Java,Multithreading,Javafx,我在“for”代码块中使用TextArea for (String s:List){ executor.execute(new Runnable() { @Override public void run() { try { textarea.appendText(s);

我在“for”代码块中使用TextArea

for (String s:List){
                executor.execute(new Runnable() {
                    @Override
                    public void run() {
                        try {
                             textarea.appendText(s);
                        } catch (IOException ignore) {}
                    }
                });
            }
TextArea不是线程安全的,我读了这个页面,所以我尝试了

public void changeArea(TextArea area, String text){
        synchronized(area) {
            area.appendText(text);
        }
    }
我修改我的“for”块

当我运行代码时,java继续给我一个错误

Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
    at com.sun.javafx.text.PrismTextLayout.addTextRun(PrismTextLayout.java:755)
    at com.sun.javafx.text.GlyphLayout.addTextRun(GlyphLayout.java:140)
    at com.sun.javafx.text.GlyphLayout.breakRuns(GlyphLayout.java:210)
    at com.sun.javafx.text.PrismTextLayout.buildRuns(PrismTextLayout.java:770)
    at com.sun.javafx.text.PrismTextLayout.layout(PrismTextLayout.java:1021)
    at com.sun.javafx.text.PrismTextLayout.ensureLayout(PrismTextLayout.java:223)
    at com.sun.javafx.text.PrismTextLayout.getBounds(PrismTextLayout.java:246)
    at javafx.scene.text.Text.getLogicalBounds(Text.java:358)
    at javafx.scene.text.Text.impl_computeGeomBounds(Text.java:1168)
    at javafx.scene.Node.updateGeomBounds(Node.java:3577)
    at javafx.scene.Node.getGeomBounds(Node.java:3530)
    at javafx.scene.Node.getLocalBounds(Node.java:3478)
    at javafx.scene.Node$MiscProperties$2.computeBounds(Node.java:6472)
    at javafx.scene.Node$LazyBoundsProperty.get(Node.java:9306)
    at javafx.scene.Node$LazyBoundsProperty.get(Node.java:9276)
    at javafx.scene.Node.getBoundsInLocal(Node.java:3156)
    at com.sun.javafx.scene.control.skin.TextAreaSkin$ContentView.layoutChildren(TextAreaSkin.java:207)
    at javafx.scene.Parent.layout(Parent.java:1087)
    at javafx.scene.Parent.layout(Parent.java:1093)
    at javafx.scene.Parent.layout(Parent.java:1093)
    at javafx.scene.Parent.layout(Parent.java:1093)
    at javafx.scene.Parent.layout(Parent.java:1093)
    at javafx.scene.Parent.layout(Parent.java:1093)
    at javafx.scene.Scene.doLayoutPass(Scene.java:552)
    at javafx.scene.Scene$ScenePulseListener.pulse(Scene.java:2397)
    at com.sun.javafx.tk.Toolkit.lambda$runPulse$2(Toolkit.java:398)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.tk.Toolkit.runPulse(Toolkit.java:397)
    at com.sun.javafx.tk.Toolkit.firePulse(Toolkit.java:424)
    at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:561)
    at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:541)
    at com.sun.javafx.tk.quantum.QuantumToolkit.pulseFromQueue(QuantumToolkit.java:534)
    at com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$11(QuantumToolkit.java:340)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.lambda$null$4(WinApplication.java:186)
    at java.lang.Thread.run(Thread.java:748)

我尝试了“锁定”并在changearea方法中添加了“同步” 当我删除
textarea.appendText
替换
system.out.println(s)
,没关系。我认为这是一个多线程安全问题

当我更改代码时

public synchronized void changeArea(TextArea area, String text){
        area.appendText(text);
    }
爪哇指出

Exception in thread "pool-2-thread-1" Exception in thread "pool-2-thread-3" java.lang.IndexOutOfBoundsException: Index: 2, Size: 2
    at java.util.ArrayList.rangeCheck(ArrayList.java:657)
    at java.util.ArrayList.get(ArrayList.java:433)
    at javafx.scene.control.TextArea$TextAreaContent.get(TextArea.java:119)
    at javafx.scene.control.TextArea$TextAreaContent.get(TextArea.java:300)
    at javafx.scene.control.TextArea$TextAreaContent.get(TextArea.java:77)
    at javafx.scene.control.TextInputControl$TextProperty.get(TextInputControl.java:1316)
    at javafx.scene.control.TextInputControl$TextProperty.get(TextInputControl.java:1300)
    at javafx.beans.binding.StringExpression.getValueSafe(StringExpression.java:62)
    at com.sun.javafx.scene.control.skin.TextAreaSkin.lambda$new$16(TextAreaSkin.java:586)
    at com.sun.javafx.binding.ExpressionHelper$Generic.fireValueChangedEvent(ExpressionHelper.java:349)
    at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:81)
    at javafx.scene.control.TextInputControl$TextProperty.fireValueChangedEvent(TextInputControl.java:1389)
    at javafx.scene.control.TextInputControl$TextProperty.markInvalid(TextInputControl.java:1393)
    at javafx.scene.control.TextInputControl$TextProperty.controlContentHasChanged(TextInputControl.java:1332)
    at javafx.scene.control.TextInputControl$TextProperty.access$1600(TextInputControl.java:1300)
    at javafx.scene.control.TextInputControl.lambda$new$0(TextInputControl.java:139)
    at com.sun.javafx.binding.ExpressionHelper$SingleInvalidation.fireValueChangedEvent(ExpressionHelper.java:137)
    at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:81)
    at javafx.scene.control.TextArea$TextAreaContent.insert(TextArea.java:207)
    at javafx.scene.control.TextInputControl.replaceText(TextInputControl.java:1204)
    at javafx.scene.control.TextInputControl.updateContent(TextInputControl.java:556)
    at javafx.scene.control.TextInputControl.replaceText(TextInputControl.java:548)
    at javafx.scene.control.TextInputControl.insertText(TextInputControl.java:473)
    at javafx.scene.control.TextInputControl.appendText(TextInputControl.java:463)
    at sample.AreaUtils.changeArea(AreaUtils.java:11)
    at sample.Scan.hikvisionScan(Scan.java:16)
    at sample.CommonUtils$1.run(CommonUtils.java:35)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)
java.lang.IndexOutOfBoundsException: Index: 2, Size: 2
    at java.util.ArrayList.rangeCheck(ArrayList.java:657)
    at java.util.ArrayList.get(ArrayList.java:433)
    at javafx.scene.control.TextArea$TextAreaContent.get(TextArea.java:119)
    at javafx.scene.control.TextArea$TextAreaContent.get(TextArea.java:300)
    at javafx.scene.control.TextArea$TextAreaContent.get(TextArea.java:77)
    at javafx.scene.control.TextInputControl$TextProperty.get(TextInputControl.java:1316)
    at javafx.scene.control.TextInputControl$TextProperty.get(TextInputControl.java:1300)
    at javafx.beans.binding.StringExpression.getValueSafe(StringExpression.java:62)
    at com.sun.javafx.scene.control.skin.TextAreaSkin.lambda$new$16(TextAreaSkin.java:586)
    at com.sun.javafx.binding.ExpressionHelper$Generic.fireValueChangedEvent(ExpressionHelper.java:349)
    at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:81)
    at javafx.scene.control.TextInputControl$TextProperty.fireValueChangedEvent(TextInputControl.java:1389)
    at javafx.scene.control.TextInputControl$TextProperty.markInvalid(TextInputControl.java:1393)
    at javafx.scene.control.TextInputControl$TextProperty.controlContentHasChanged(TextInputControl.java:1332)
    at javafx.scene.control.TextInputControl$TextProperty.access$1600(TextInputControl.java:1300)
    at javafx.scene.control.TextInputControl.lambda$new$0(TextInputControl.java:139)
    at com.sun.javafx.binding.ExpressionHelper$SingleInvalidation.fireValueChangedEvent(ExpressionHelper.java:137)
    at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:81)
    at javafx.scene.control.TextArea$TextAreaContent.insert(TextArea.java:207)
    at javafx.scene.control.TextInputControl.replaceText(TextInputControl.java:1204)
    at javafx.scene.control.TextInputControl.updateContent(TextInputControl.java:556)
    at javafx.scene.control.TextInputControl.replaceText(TextInputControl.java:548)
    at javafx.scene.control.TextInputControl.insertText(TextInputControl.java:473)
    at javafx.scene.control.TextInputControl.appendText(TextInputControl.java:463)
    at sample.AreaUtils.changeArea(AreaUtils.java:11)
    at sample.Scan.hikvisionScan(Scan.java:16)
    at sample.CommonUtils$1.run(CommonUtils.java:35)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)

在JavaFX平台线程上运行您的操作,您将不会再看到此问题

public void changeArea(TextArea area, String text) {
    Platform.runLater(()-> area.appendText(text));
}

在JavaFX平台线程上运行您的操作,您将不会再看到此问题

public void changeArea(TextArea area, String text) {
    Platform.runLater(()-> area.appendText(text));
}

看看当我删除
textarea.appendText
并替换
system.out.println
时,它是正常的。我认为这是一个多线程安全问题,您不能将节点(或任何属性)从fx应用程序线程中更改。这条规则也不例外。将JavaFx应用程序视为在单个线程上运行的应用程序。正如kleopatra所写,对gui的所有更改都必须在该线程上完成。要获得“我应该做什么”的答案,请发布或尝试查看一些示例,如一个。将附加代码放在FX线程-
平台上。稍后运行(()->area.appendText(…)
。请查看我删除
textarea.appendText
并替换
system.out.println时的情况
,没关系。我认为这是一个多线程安全问题。您不能从fx应用程序线程更改节点(或任何属性)。该规则也不例外。将JavaFx应用程序视为在单个线程上运行的应用程序。正如kleopatra编写的,对gui的所有更改都必须在该线程上完成。若要获得以下问题的答案:我应该做什么,发布或尝试回顾一些示例,比如一个。将追加代码放在FX线程-
平台上。稍后运行(()->区域。追加文本(…)