SWT中多線程的處理

SWT中處理多線程

Eclipse中,SWT是最重要的基石之一,負責了跨平臺的本地界面顯示,使Java也能夠編寫與系統相同的界面元素。在SWT中處理多線程也是其重要技術的表現。

SWT有兩個使用方法,分別是asyncExecsyncExec,前者是 異步執行與界面有關的操作,後者反之。爲什麼要這麼做?由於SWT單獨有一個線程(主線程)處理界面顯示,數據顯示等,如果要在其他線程中操作界面元素, 就必須使用上述兩個方法執行,即將另外線程的操作交給主線程處理。

SWT的多線程遠沒有這麼簡單。一般情況下,在SWT中運行線程時,其主線程不能阻塞,也能響應用戶請求,比如鼠標和菜單等。在這種情況下,需要新建Thread來處理邏輯,在這個Thread中,必須使用上面的兩個方法處理界面數據。

以下是一個簡單的例子,啓動10個線程,在5秒的時間內,刷新列表中各行的字符串,在這個過程中,主界面依然能夠響應鼠標請求。代碼有點圓環套圓環的感覺。

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.Shell;

/**
 @author tenyears.cn
 */
public class SWTThread {
  private int size = 10// 10 threads
  private long runTime = 5000// 5 seconds
  private List list;
  private Shell shell;
  public void startThread() {
    for (int index = 0; index < size; index++) {
      final int listIndex = index;
      final Runnable refresh = new Runnable() {
        public void run() {
          final Display disp = shell.getDisplay();
          final Runnable runOne = new Runnable() {
            public void run() {
              final long start = System.currentTimeMillis();
              while ((System.currentTimeMillis() - start) < runTime) {
                disp.syncExec(new Runnable() {
                  public void run() {
                    if (list.isDisposed())
                      return;
                    String string = "No." + listIndex;
                    string += " " + (System.currentTimeMillis() - start);
                    list.setItem(listIndex, string);
                  }
                });
                try {
                  Thread.sleep(100);
                catch (InterruptedException e) {
                }
              };
            }
          };
          Thread thread = new Thread(runOne);
          thread.start();
        }
      };
      BusyIndicator.showWhile(shell.getDisplay(), refresh);//
這一句很關鍵
    }
  }

  public Shell open(final Display display) {
    shell = new Shell(display, SWT.DIALOG_TRIM | SWT.MIN);
    shell.setText("SWT Thread Test");
    shell.setLayout(new GridLayout(1true));
    list = new List(shell, SWT.BORDER);
    list.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
    for (int index = 0; index < size; index++)
      list.add("String " + (index + 1));
    Button startBtn = new Button(shell, SWT.PUSH);
    startBtn.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
    startBtn.setText("Start");
    SelectionAdapter selection = new SelectionAdapter() {
      public void widgetSelected(SelectionEvent e) {
        startThread();
      }
    };
    startBtn.addSelectionListener(selection);
    shell.setSize(400300);
    shell.open();
    return shell;
  }

  public static void main(String[] args) {
    Display display = new Display();
    SWTThread application = new SWTThread();
    Shell shell = application.open(display);
    while (!shell.isDisposed()) {
      if (!display.readAndDispatch())
        display.sleep();
    }
    display.dispose();
  }
}

說明:

下面分析startThread()

這個方法可以用於當這個方法的執行需要很長時間,而在其執行期間又不會影響其他方法的執行。本方法中的最後一句:

BusyIndicator.showWhile(shell.getDisplay(), refresh);

是關鍵,如果沒有這一句則,執行此方法時,其他方法不能運行。

這個方法的必須包含兩個Runnable的是實現:其中外層用於

BusyIndicator.showWhile()方法中作爲參數

長時間的運行代碼應該放在裏面的一個runnable實現的run()方法中,例如:

 

final Runnable runOne = new Runnable() {

        public void run() {

        final long start = System.currentTimeMillis();

         while ((System.currentTimeMillis() - start) < 1000*10) {

                       cnt++;

                  }            

               };

       };      

 

startThread方法可以簡化爲:(這個方法更清晰)

   

public void startThread() {

      

          final Runnable refresh = new Runnable() {

            public void run() {

             

              final Runnable runOne = new Runnable() {

                public void run() {

                  final long start = System.currentTimeMillis();

                  while ((System.currentTimeMillis() - start) < 1000*10) {

                        cnt++;

                   }            

                  };

                };            

              Thread thread = new Thread(runOne);

              thread.start();

            }

          };

          BusyIndicator.showWhile(shell.getDisplay(), refresh);

        }

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章