j2ME多线程网络编程

   

网络编程中的多线程

  由于目标设备具有内存小,计算能力弱和电池供电等特点,所以如何使应用程序高效的运行就成为开发中的一个大问题.尤其针对手机等移动信息设备时,无线通讯的特点又对我们的程序提出了更高的要求.从代码优化的角度,在网络编程中引入多线程就显得十分重要。

  当程序运行的时候,Application Management Software(应用管理软件)首先初始化一个MIDlet,然后调用它的startApp()方法使得MIDlet进入active状态,这条程序分支就是主线程,它执行其他的方法后都会返回到这个分支上来继续执行。然而网络连接是个可能堵塞的操作,意味着它可能长时间都不返回。

  在SUN公司的无线开发包WTK中模拟一段网络连接程序运行时,WTK会提示网络连接工作可能会堵塞用户输入,需要创建另外一个线程去进行联网操作。针对以上情况,引入多线程的处理机制。

  1. 利用Thread类与Runnable接口

  编写J2ME网络连接应用程序的时候往往借助Command显示部件,调用其事件处理函数完成网络的连接工作,代码框架如下:

public void commandAction(Command c, Displayable s) {
 if(c==sendCommand){
requestConnect();//连接方法
 }
 else if(
c==backCommand){
 display.setCurrent(mainForm); }
 else{
destroyApp(false);
notifyDestroyed(); }
}
// 获取一个HTTP的连接
private void requestConnect() {
 String url= URL.URLString
 HttpConnection hpc = null;
 try{
hpc = (HttpConnection)Connector.open(url);
int status = hpc.getResponseCode();
if(status != HttpConnection.HTTP_OK)
 content = "联机失败!";
else
 content = "已联机!";
 }
 catch(IOException e){System.out.println(content);}
 try{
if(hpc != null) hpc.close();
 }
 catch(IOException e2){}}

上面的程序工作原理可用图2的工作原理图a来表示。

  图2 工作原理图a

  分析图2可以得出,如果这样的网络连接程序在手机上运行,那么将可能长时间得不到响应。因为连接工作只有一个主线程,所有的应用都是在这个主线程当中进行的,如果此主线程不返回,那么就不能进行后面的行为,用户也不能进行任何操作。

  下面改进一下程序,创建一个实现Runnable接口的ConnectPipe类来创建多线程。代码如下:

//实现Runnable接口
class ConnectPipe implement Runnable{
  ……
  public void run(){
  requestConnect();}
  }

  修改commandAction函数:

public void commandAction(Command c, Displayable s) {
 if(c==sendCommand){
//创建新线程
new Thread(new ConnectPipe()).start();
 }
 else if(c==backCommand){
……
 }
}

  修改之后程序能够较为顺利的运行,当处理网络连接的时候,启动一个线程后主线程会立刻返回,两个线程并行,不会引发在此地堵塞。其工作原理可用图3的工作原理图b来表示。

  图3 工作原理图b

  详细分析图3,又发现尽管程序可以正常工作,但是每次用户按下按钮的时候都会有新的线程产生,这样显然不够高效,同时,异步的行为又有可能使两个线程间产生死锁。幸好java中提供了wait()和notify()/notifyAll()来进行线程间的通讯,协调同步问题。那么对应本程序中的线程同步问题,设计思想如下:启动线程后,让其进入等待的状态,当用户激活Command事件的时候唤醒线程,才让其继续运行。代码类似如下:

public synchronized void run() {
 while (dealing) {
try { wait(); }//线程等待
catch (InterruptedException ie) {}
if (dealing) requestConnect();
 }
}
public synchronized void deal() {
 notify();//唤醒线程
}

  其中dealing变量用于定义一个锁,当其为true时,当前线程等待,直到用户激活Command事件之后,调用deal()方法中的notify()唤醒当前线程继续运行。这样程序就显得相当的高效,也在很大程度上避免了线程间的死锁问题。其工作原理可用图4的工作原理图c来表示。

  图4 工作原理图c

  2. 利用系统类Timer和TimerTask

  系统类Timer类是一个计时器,和TimerTask类结合可以来实现在MIDlet中定时执行特定任务。需要说明的是每一个Timer对象实际上都是一个后台运行的独立的线程。这是因为调度一次的任务都是由TimerTask类的实现对象负责,TimerTask类是一个抽象类,它的主要特点是实现了Runnable接口,因此扩展了必须实现的public void run()方法。

  所以,在J2ME的网络编程中,我们可以利用Timer类和TimerTask类来建立线程,完成网络连接等工作。设计思想如下:创建一个Timer类计时器,一个完成网络连接功能的TimerTask类,在系统空闲时,反复调度任务要求连接,直到连接成功,再调用TimerTask类的cancel()可以停止一个具体的调度任务。核心代码类似如下:

class ConnectTimer implement TimerTask{
 ConnectTimer (){
m_Timer = new Timer();//定义Timer
m_Timer.schedule(this,500,5000); //调度任务
 }
 ……
 public synchronized void run(){
requestConnect();//连接方法
cancel();//取消任务
 }
}
public void commandAction(Command c, Displayable s) {
 if(c==sendCommand){
new ConnectTimer;}
 else if(c==backCommand){
……
 }
}

  结束语

  综上所述,在J2ME的应用开发中网络程序的设计具有重要的地位,而编程的关键又在于编写高效友好的J2ME网络连接程序。通过Java语言内置的多线程处理机制,利用线程进行同步并行处理,解决了网络连接时的阻塞问题,达到了程序高效运行的目的。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值