0

I have a problem in regards to parallelism in javafx. More specifically, dividing the canvas of my program to run with multiple threads. When compiled, the program glitches out and doesn't work as supposed to. The code in the thread class is supposed to print out the Mandelbrot set, and the code in the application class is dividing the canvas into different parts that each should run in parallel. Here is

I found that adding thread.join() fixes the problem, but then the program is ran on a single thread. Could anyone help me out resolve this issue?

tino
  • 11
  • 1
  • 1
    [mcve] please.. – kleopatra Feb 03 '23 at 09:08
  • 2
    please read the referenced help page and act accordingly.. that said: you __must not__ access a node in an active scenegraph off the fx application thread – kleopatra Feb 03 '23 at 09:28
  • 2
    You must not modify the UI from a background thread. – James_D Feb 03 '23 at 13:46
  • 1
    See if the ideas from [here](https://stackoverflow.com/questions/44050344/timing-javafx-canvas-application/44056730#44056730) can help. – SedJ601 Feb 03 '23 at 15:00
  • 1
    https://stackoverflow.com/questions/44136040/performance-of-javafx-gui-vs-swing – SedJ601 Feb 03 '23 at 15:01
  • See also [`MandelbrotSet`](https://github.com/openjdk/jfx/tree/master/apps/samples/MandelbrotSet), [_loc. cit.](https://stackoverflow.com/a/44141878/230513) – trashgod Feb 03 '23 at 18:22
  • @trashgod I haven't looked at that code in enough detail, but simply synchronizing on the `PixelWriter` isn't going to make updating it from a background thread safe (maybe there is something else going on in the code that does make it safe). You'd have to know the `WritableImage` or `Canvas` was synchronizing on the `PixelWriter` (which it almost certainly isn't, as it's not designed to be multithreaded). – James_D Feb 03 '23 at 19:40
  • @James_D: I strongly endorse your point about [sufficient conditions](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/package-summary.html) for thread safety; in this case, the explicit synchronization is confined to the background thread of a `javafx.concurrent.Task`. – trashgod Feb 04 '23 at 00:15
  • Thank you all for the detailed asnwers. Which part is the biggest problem if I may ask, (in the thread class) the if statements, the canvas .getGraphicsContent2D or both? Thanks again – tino Feb 05 '23 at 04:04
  • @tino Probably, they are all problems. The rule is not to do *anything* with the active scene graph or properties related to it off the JavaFX thread. That includes writing *or reading* attributes of nodes (like canvas height and width) or drawing images to a canvas graphics context. The Task javadoc provides some advice on how to work with multi-threading and JavaFX. – jewelsea Feb 07 '23 at 00:32

1 Answers1

2

What you are trying to do cannot be done with a Canvas because of the fx application thread restiction which has already been mentioned.

But it can be done via the WritableImage of JavaFX 13+ with support for Buffers. Writing into the buffer is not restricted in the above way and can thus be done in parallel with high performance.

I have compiled some examples (not any parallel ones) of how to use WritableImages with Buffers here: https://github.com/mipastgt/JFXToolsAndDemos

mipa
  • 10,369
  • 2
  • 16
  • 35
  • *"Writing into the buffer is not restricted"*. This makes some kind of intuitive sense to me, but is it documented anywhere that the buffer is thread-safe? – James_D Feb 03 '23 at 16:00
  • As an example, this [`MandelbrotSet`](https://github.com/openjdk/jfx/tree/master/apps/samples/MandelbrotSet) synchronizes on the `PixelWriter`. I infer that is not so much _thread_safe_ as _useable_ with the usual [caveats](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/package-summary.html). – trashgod Feb 03 '23 at 18:31
  • 3
    The key element is the updateBuffer method which must be called on the fx application thread and calling this must be synchronized with your threads. In one of my examples I implemented double buffering that way so that you can write into one part of the buffer and show the other part and then switch the viewport in the updateBuffer method. – mipa Feb 03 '23 at 19:24
  • Thank you all for the detailed asnwers. Which part is the biggest problem if I may ask, (in the thread class) the if statements, the canvas .getGraphicsContent2D or both? Thanks again – tino Feb 05 '23 at 04:04