分类:
2008-10-16 18:22:21
本文分析了Eclipse中多线程程序的实现,讨论了在Eclipse客户端程序开发中应用多线程的方法和要注意的问题,同时也讨论了多线程程序的一些调试和问题解决的方法。
Eclipse作为一个开发平台,使用越来越广泛,基于Eclipse Rich Client Platform开发的客户端程序也越来越多。在当今越来越复杂的应用环境中,我们的客户端程序不可避免的要同时进行多任务的处理。一个优异的客户端程序都会允许用户同时启动多个任务,从而大大提高用户的工作效率以及用户体验。本文中我们来谈谈Eclipse中实现多任务的方式。
在我们基于Eclipse的程序中,我们有很多种方式提供多任务的实现。熟悉的朋友立即会想到Java的Thread类,这是Java中使用最多的一个实现多任务的类。Eclipse平台为多任务处理提供了自己的API,那就是Job以及UIJob。Eclipse中的Job是对Java Thread的一个封装,为我们实现多任务提供了更方便的接口。以下是Job的基本用法:
Job job = new Job(“Job Name”){ protected IStatus run(IProgressMonitor monitor) { // 在这里添加你的任务代码 return Status.OK_STATUS; } }; job.schedule(delayTime); |
在Eclipse中我们也会经常用到Display.asynchExec() 和Display.synchExec()来启动任务的执行。这两个方法主要为了方便我们完成界面操作的任务。以下是Display.asynchExec()的用法,Display.synchExec()和它类似。
Display.getDefault().asyncExec(new Runnable() { public void run() { // 在这里添加你的任务代码 } }); |
通常,在Eclipse中我们最好使用Eclipse提供的Job接口来实现多任务,而不是使用Java的thread。为什么呢?主要有以下几个原因:
下面我们从几个方面来讨论Eclipse中Job的实现和使用方面的问题。
Eclipse中Job的实现
Eclipse的核心包中提供了一个JobManager类,它实现了IJobManager接口,Eclipse中Job的管理和调度都是由JobManager来实现的。 JobManager维护有一个线程池,用来运行Job。当我们调用Job的schedule方法后,这个Job会被JobManager首先放到一个Job运行的等待队列中去。之后,JobManager会通知线程池有新的Job加入了运行等待队列。线程池会找出一个空闲的线程来运行Job,如果没有空闲线程,线程池会创建一个新的线程来运行Job。一旦Job运行完毕,运行Job的线程会返回到线程池中以备下次使用。从上面Job运行的过程我们可以看到,JobManager介入了一个Job运行的全过程,它了解Job什么时候开始,什么时候结束,每一时候Job的运行状态。JobManager将这些Job运行的信息以接口的方式提供给用户,同时它也提供了接口让我们可以介入Job的调度等,从而我们拥有了更加强大的控制Job的能力。
为了我们更方便的了解Job所处的状态,JobManager设置Job的一个状态标志位,我们可以通过Job的getState方法获得Job当前的状态值以了解其状态:
Eclipse中的UI线程
另外,在Eclipse的线程处理中,有一个UI线程的概念。Eclipse程序中的主线程是一个特殊的线程,程序启动后会先执行这个线程,也就是我们的main()函数所在的线程。作为桌面应用程序,我们的主线程主要负责界面的响应以及绘制界面元素,所以通常我们也叫它UI线程。
以下代码,编过SWT应用程序的读者会非常熟悉。它一般出现在main函数的结尾。下面来仔细分析一下它的详细情况。
//当窗口未释放时 while (!shell.isDisposed()) { //如果display对象事件队列中没有了等待的事件,就让该线程进入等待状态 if (!display.readAndDispatch()) display.sleep(); } |
上面的程序实际上就是我们UI线程的处理逻辑:当程序启动后,UI线程会读取事件等待队列,看有没有事件等待处理。如果有,它会进行相应处理,如果没有它会进入睡眠状态。如果有新的事件到来,它又会被唤醒,进行处理。UI线程所需要处理的事件包括用户的鼠标和键盘操作事件,操作系统或程序中发出的绘制事件。一般来说,处理事件的过程也就是响应用户操作的过程。
一个好的桌面应用程序需要对用户的操作作出最快的响应,也就是说我们的UI线程必须尽快的处理各种事件。从我们程序的角度来说,在UI线程中我们不能进行大量的计算或者等待,否则用户操作事件得不到及时的处理。通常,如果有大量的计算或者需要长时间等待(例如进行网络操作或者数据库操作)时,我们必须将这些长时间处理的程序单独开辟出一个线程来执行。这样虽然后台运行着程序,但也不会影响界面上的操作。
除主线程之外的所有线程都是非UI线程。在Eclipse程序中,我们所有对界面元素的操作都必须放到UI线程中来执行,否则会抛出Exception,所以我们要区分出UI线程和非UI线程,保证我们对UI的操作都在UI线程中执行。
如何判断当前线程是否UI线程: 你可以通过调用Display.getCurrent()来知道当前线程是否是UI线程。如果Display.getCurrent()返回为空,表示当前不是UI线程。
[1]