justik justik - 23 days ago 4
Java Question

Java, multi-thread application,working main window when computing

I would like to ask for advice how to design the application. Currently, I would like to rewrite a statistical application processing large data into a multi-thread version. My primary language is C++, sorry for my slightly beginner question :-).

The existing application is based on the following model. There is a MainWindow class continuously displaying previous results involving current zoom operation (GUI). Each statistical computation is based on the own class picking up the input data, performing the computation, showing results and its visualization (based on swing).

Unfortunately, the library is not written as multi-thread. It has an undesirable consequence: while a computation is running, it is impossible to work with MainWindow (browsing all results until new are obtained); it is "frozen"...

Yesterday, I tried to propose a single conceptual update:

public class MainWindow extends JFame {

private void fButtonActionPerformed(java.awt.event.ActionEvent e) {
//Get data, single thread
Matrix A = getData(); //Input data (block matrix)
Matrix B; //Output data (block matrix)

//Computation in a separate thread
FunctionMT f = new FunctionMT (A, B);
Thread t = new Thread(f);
t.start(); // Starting the thread

//Display results in a form
results.print(B);

//Update graphic results
scene.update(B);
scene.repaint();
}


The sample function class FunctionMT extends Thread library

public class FunctionMT extends Thread{
private final Matrix A;
private Matrix B;

public FunctionMT (final Matrix A_, Matrix B_) {A = A_; B = B_;}
public void run () { spDecomposition();}
public void spDecomposition() {
for (int i = 0; i < A.size; i++)
for (int j = 0; j < A.size; j++)
B(i,j) = f(A(i,));} //Some computationally hard step
}


The matrix A is the input matrix, B represents the output. The computation is performed in a single thread working with FunctionMT instance...

When a computation is run in a single thread, it is possible to work with the main window. Unfortunately, results are repainted before the computation is stopped.

I tried to add a join method()

...
Thread t = new Thread(f);
t.start(); // Starting the thread

try{t.join();} //Wait for its end
catch(InterruptedException e) {e.printStackTrace();}

results.print(B);

scene.update(B);
scene.repaint();
...


which waits until the results are processed.Unfortunately, it makes the main window frozen.

How to propose a multi-thread computation to be able to work with a main window during the computation as well as the form waits until the computation is finished?

Is it possible to add some function that processs system messages into for cycle ?

for (int i = 0; i < A.size; i++)
for (int j = 0; j < A.size; j++)
processSystemMessages();
B(i,j) = f(A(i,));}


Another solution may join the computation algorithms and showing the results into the same thread, but it looks ugly :-) and breaks the design pattern.

Thank you very much for your help...

Answer

Try this:

UPDATE: looser coupling

public class MainWindow extends JFrame {

    private void fButtonActionPerformed(java.awt.event.ActionEvent e) {

        // ...

        FunctionMT f = new FunctionMT (A, B, new Runnable() {
            @Override
            public void run() {
                results.print(B);
                scene.update(B);
                scene.repaint();
            }
        });
        Thread t = new Thread(f);
        t.start();

        // Wait for computation:
        // won't do it here.
        // results.print(B);
        // scene.update(B);
        // scene.repaint();
    }
}
public class FunctionMT extends Runnable {

    // ...

    private Runnable callback;

    public FunctionMT (final Matrix A_, Matrix B_, Runnable callback) {

        // ...

        this.callback = callback;
    }

    private void spDecomposition() {

        // Do computation.

        SwingUtilities.html.invokeLater(callback);
    }
}
Comments