0

I use TextArea in a "for" code block

for (String s:List){
                executor.execute(new Runnable() {
                    @Override
                    public void run() {
                        try {
                             textarea.appendText(s);
                        } catch (IOException ignore) {}
                    }
                });
            }

TextArea is not thread safe, i read this page pageso i tried

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

I modify my "for" block

changeArea(textarea, "sth");

When I run the code,java continues to give me a mistake

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)

I tried "lock" and add "synchronized" in the changearea method When I delete textarea.appendText(s) and replace system.out.println(s) , its ok.I thought this is a Multithreading safe issues

When i change my code

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

java point out

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)
notyeat
  • 33
  • 1
  • 7
  • Have a look at [What is a NullPointerException, and how do I fix it?](https://stackoverflow.com/questions/218384/what-is-a-nullpointerexception-and-how-do-i-fix-it) – khelwood Feb 07 '20 at 15:04
  • When I delete ```textarea.appendText(s)``` and replace ```system.out.println(s)```, its ok.I thought this is a Multithreading safe issues – notyeat Feb 07 '20 at 15:11
  • When i change my code ```public synchronized void changeArea(TextArea area, String text){ area.appendText(text); }``` java point out me “Exception in thread "pool-2-thread-1" Exception in thread "pool-2-thread-3" java.lang.IndexOutOfBoundsException: Index: 2, Size: 2” – notyeat Feb 07 '20 at 15:12
  • 1
    you must not change nodes (nor any of there properties) off the fx application thread. No exception to that rule. – kleopatra Feb 07 '20 at 15:33
  • I need append TextArea text in Multithreading, What should I do? – notyeat Feb 07 '20 at 15:38
  • 2
    Think of JavaFx Application as an application that runs on a single thread. As kleopatra wrote all changes to gui must be done on that thread. To get an answer to "what should I do, post [mre] or try to review some examples like [this](https://stackoverflow.com/a/55550186/3992939) one. – c0der Feb 07 '20 at 15:56
  • 1
    Put the append-code on the FX thread—`Platform.runLater(() -> area.appendText(...))`. – Slaw Feb 07 '20 at 15:56

1 Answers1

3

Run your operations on the JavaFX Platform thread and you should no longer see this issue.

public void changeArea(TextArea area, String text) {
    Platform.runLater(()-> area.appendText(text));
}
Joe
  • 1,316
  • 9
  • 17