Sunday, August 19, 2012

Be careful with Java Thread.join() in GUI design

I was stuck by a problem for about a week. Every time I tried to run the GUI,the GUI was frozen, no buttons, menus or any other operations could be done until all the back-end computations finished.
Finally I figured out the cause of the problem. Since I'm using parallel programming. I created a thread when a new transaction was required, and I joined all the threads when they finished. I created threads with following code:


Thread threadArray[] = new Thread[testThreadNmuber];
for(int i=0; i<testThreadNmuber; i++)
{
    threadArray[i] = new Thread(testDriver);
    threadArray[i].start();  
}

Above code worked fine. I thought I should be able to use the similar way to join the threads. Therefore I wrote following code:

for(int i=0; i<testThreadNmuber; i++)
{
    threadArray[i].join();
    System.out.println("Thread-" +i+ " : exited\n");
}
However, the join() function caused a critical error. I didn't realize the problem of join(), because it was the common way to implement in Java parallel programming. While I understood the problem by reading the Java API. In Java API the explanation of join() is 'Waits for this thread to die'. As I called the join() in the main thread, the main thread would wait for all the sub-threads to die. In GUI design, the main thread is the thread that draw the interface. If the interface waits all the sub-threads to die the main thread will hold up and the interface will not response any operations. Therefore, I should not use join() in GUI programming.


However this cause another problem. If I don't use join(), how I can know if all the jobs finish? One simple solution is to create a integer, if one thread finish, the integer plus one. When this integer is equal to the number of threads, all the thread finish. But this integer must be locked when one thread is updating it, otherwise the race condition may occur.


Saturday, August 11, 2012

Progress Bar

The performance testing requires a very long time, we need to know the progress of the testing.
Progress bar is a common choice.Progress bar is provided as a component by Java SWT. To add a progress bar, following steps can be used:
1. Create ProgressBar object, and choose the style, such as: ProgressBar bar1 = new ProgressBar (shell, SWT.HORIZONTAL | SWT.SMOOTH);.
2. Set the maximum value and minimum value, bar1.setMaximum(100);
3. Set the progress of the ProgressBar in a long time task, progressBar.getSelection() + 1.

Progress bar should be used with thread. The threads that are not UI thread cannot write the UI directly, otherwise the UI will be frozen, no more operations can be done with the UI. It is the same reason that the progress bar must update the UI in a separate thread.

Here is how I did to create the progress bar:

final ProgressBar progressBar = new ProgressBar(composite, SWT.SMOOTH);
    FormData fd_progressBar = new FormData();
    fd_progressBar.top = new FormAttachment(0);
    fd_progressBar.right = new FormAttachment(100, -42);
    progressBar.setLayoutData(fd_progressBar);
    class ProgressBarRunning extends Thread{
         long testRuntime = Integer.parseInt(text_1.getText());
         public void run() {
      for (int i = 0; i < 100; i++) {
  try {
                    Thread.sleep(testRuntime/100);
                } catch (InterruptedException e) {
               e.printStackTrace();
}
display.asyncExec(new Runnable() {
      public void run() {
if (progressBar.isDisposed())
    return;
progressBar.setSelection(progressBar.getSelection() + 1);
        }
   });
  }
  }
}

In the above code, the first thread decides how long the progress bar increase. The second thread updates the progress bar.


Friday, August 3, 2012

Introducing Java SWT

I have been using Java Swing for a while, I have some personal view of points about Swing.

It is very hard for a beginner to build a good looking GUI with Swing. Without further knowledge of Swing, the GUI doesn't look like a proper software.The  appearance doesn't fit the current system.

Swing is not thread-safe. Thread is the core of front-end design of this project. I need to care about which thread is updating GUI. If something goes wrong, some unpredictable behaviors will happen.

I have introduced Java SWT into my GUI design base on following reasons.

Java SWT always fits the current operation system. The GUI is friendly to users.

Java SWT will throw exceptions when threads go wrong which is better than the uncertainty of Java Swing.

Java SWT runs faster than Java Swing, since my job is performance test, I want to reduce the influence of GUI to the performance of the test.

However Java SWT is not perfect. I need to worry about the compatibility of Java SWT on the Non-Windows platforms. The Java SWT is not included in the standard JRE package, it needs to be installed.