程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> J2ME >> 編寫高效友好的多線程J2ME聯網應用

編寫高效友好的多線程J2ME聯網應用

編輯:J2ME
初次編寫J2ME的聯網應用程序的時候往往會寫出這樣的代碼:
public void commandAction(Command c, Displayable s) {
    if (c == mExitCommand)
      notifyDestroyed();
    else if (c == mConnectCommand)
      connect();
}
 
  private void connect() {
    String url = getAppProperty("NetworkThreading.URL");
   
    try {
     
      HttpConnection hc = (HttpConnection)Connector.open(url);
      InputStream in = hc.openInputStream();
     
      int contentLength = (int)hc.getLength();
      if (contentLength == -1) contentLength = 255;
      byte[] raw = new byte[contentLength];
........
.......
}
當你運行這樣的程序的時候會出現什麼問題呢?wtk會提示你聯網工作可能會堵塞用戶輸入,讓你到另外一個線程去進行聯網操作。OK,那麼我們按照他的要求新建一個線程來進行聯網,比如這樣寫:
public void commandAction(Command c, Displayable s) {
  if (c == mExitCommand)
    notifyDestroyed();
  else if (c == mConnectCommand) {
    Thread t = new Thread() {
      public void run() {
        connect();
      }
    };
    t.start();
  }
}
這樣聯網就可以通過了,那麼為什麼會這樣呢?明白事物背後的原理顯得非常的重要,下面我做一下介紹,當程序運行的時候,Application Management Software(應用管理軟件)首先初始化一個MIDlet,然後調用他的startApp()方法使得MIDlet進入active狀態,這條程序分支就是主線程,他執行其他的方法後都會返回到這個分支上來繼續執行。然後聯網是個可能堵塞的操作,意味著他可能長時間都不返回。我曾經寫的聯網程序在手機上運行,的確比較耗費時間。如果他不返回,那麼就不能進行後面的操作,用戶也不能輸入。這樣看上去手機就像死了一樣,這顯然不夠友好。看看下面的原理圖吧:
Hijacking the system event thread
當我們在應用程序中新建一個線程來處理聯網或者浏覽大量RMS數據的時候就不一樣了。這時候啟動線程後主線程會立刻返回,不會堵塞。
Using a new thread for network activity
仔細想想這樣同樣有不好的地方,盡管他可以正常工作,但是每次用戶按下按鈕的時候都會有新的線程產生,這樣顯然不夠高效。幸好Java中提供了wait()和notify()/notifyAll()來協調這樣的問題,我們啟動線程後讓他進入等待的狀態,當用戶按下按鈕的時候才讓他繼續運行。代碼類似這樣:
public synchronized void run() {
  while (mTrucking) {
    try { wait(); }
    catch (InterruptedException IE) {}
    if (mTrucking) connect();
  }
}

public synchronized void go() {
  notify();
}
Using a single worker thread
這樣效率比較高了!當用戶進行聯網操作的時候我們應該做一個提示界面,比如一個動畫告訴用戶正在進行聯網操作。這樣比較友好。那麼當用戶選擇聯網動作的時候,我們讓我提前做好的歡迎界面顯示在屏幕上,聯網結束後再把返回的結果顯示出來。這樣就是一個出色的聯網應用程序了。下面的這個代碼可以在屏幕上描繪一個動畫的效果,當然你也可以修改一下做成自己喜歡的樣子。
import Java.util.*;

import Javax.microedition.lcdui.*;

public class WaitCanvas
    extends Canvas {
  private int mCount, mMaximum;
  private int mInterval;
 
  private int mWidth, mHeight, mX, mY, mRadius;
  private String mMessage;
 
  public WaitCanvas() {
    mCount = 0;
    mMaximum = 36;
    mInterval = 100;
   
    mWidth = getWidth();
    mHeight = getHeight();
   
    // Calculate the radius.
    int halfWidth = (mWidth - mRadius) / 2;
    int halfHeight = (mHeight - mRadius) / 2;
    mRadius = Math.min(halfWidth, halfHeight);
   
    // Calculate the location.
    mX = halfWidth - mRadius / 2;
    mY = halfHeight - mRadius / 2;

    // Create a Timer to update the display.
    TimerTask task = new TimerTask() {
      public void run() {
        mCount = (mCount + 1) % mMaximum;
        repaint();
      }
    };
    Timer timer = new Timer();
    timer.schedule(task, 0, mInterval);
  }
 
  public void setMessage(String s) {
    mMessage = s;
    repaint();
  }
 
  public void paint(Graphics g) {
    int theta = -(mCount * 360 / mMaximum);
   
    // Clear the whole screen.
    g.setColor(255, 255, 255);
    g.fillRect(0, 0, mWidth, mHeight);
   
    // Now draw the pinwheel.
    g.setColor(0, 0, 0);
    g.drawArc(mX, mY, mRadius, mRadius, 0, 360);
    g.fillArc(mX, mY, mRadius, mRadius, theta +  90, 90);
    g.fillArc(mX, mY, mRadius, mRadius, theta + 270, 90);
   
    // Draw the message, if there is a message.
    if (mMessage != null)
      g.drawString(mMessage, mWidth / 2, mHeight,
          Graphics.BOTTOM | Graphics.HCENTER);
  }
}

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved