Skip to main content

Real multi-threading in JavaFX

Posted by malenkov on August 13, 2010 at 6:33 AM PDT

I developed my first implementation of the Reversi game on BASIC 20 years ago. Since then, I ported it on each programming language I studied: Turbo Pascal with graphics library and Turbo Vision, C with the Windows API, C++ with the ClanLib, Java AWT applet, and Swing application with Java2D. Now I am ready to publish yet another implementation, on JavaFX Script.

This game allows to compete with one of the algorithms as well as to see how these algorithms compete with each other. The Sergey algorithm is based on the Minimax algorithm with a simple table of game piece weights where the calculation depth is 6. The Pavel algorithm is developed by my colleague, and I have got it from the official JavaFX site. But I had to add the following constructor:

public Board(GameBoard board) {
    this();
    Object dark = board.getFriend();
    Object light = board.getEnemy();
    int pos = 11;
    for (int y = 0; y < 8; y++, pos += 2) {
        for (int x = 0; x < 8; x++, pos++) {
            Object piece = board.getPiece(x, y);
            this.data[pos] = (piece == dark)
                ? PIECE_DARK
                : (piece == light)
                    ? PIECE_LIGHT
                    : PIECE_EMPTY;
        }
    }
    this.movePiece = PIECE_DARK;
    prepareMoves();
}

When I increased the calculation depth, I discovered that the search function started blocking the UI. The rationale is that the Timeline class invokes all functions from key frames on the thread which renders UI. I decided to override the abstract JavaTaskBase class and implement the RunnableFuture interface to avoid extra entities:

public class JavaTask extends JavaTaskBase, RunnableFuture {
  override function create() {
    this
  }
  override function run() {
    // do something
  }
}

However, I found out that the RunnableFuture interface must be implemented on Java, i.e. it is prohibited to use FX objects. It seems to me that in this case the JavaTaskBase class should not be an abstract class. It should be initialized via a public variable as in my JavaTask class:

public class JavaTask extends JavaTaskBase {
  public-init var runnable: RunnableFuture on replace {
    start()
  }

  override function create() {
    runnable
  }
}

Note that JavaFX does not support thread synchronization. Be careful!

If you know how to use the invokeLater method of the EventQueue class to split a long tasks, you can use the deferAction method of the FX class in the same way. This method invokes a function on the thread which renders the UI. Thus, you don't need synchronization in this case.

Also Baechul's Weblog will be useful.

original post

Related Topics >>