ImageVerifierCode 换一换
格式:DOCX , 页数:14 ,大小:245.61KB ,
资源ID:10291882      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/10291882.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(Eclipse客户端程序中多线程的使用.docx)为本站会员(b****8)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

Eclipse客户端程序中多线程的使用.docx

1、Eclipse客户端程序中多线程的使用Eclipse 客户端程序中多线程的使用Eclipse 作为一个开发平台,使用越来越广泛,基于 Eclipse Rich ClientPlatform 开发的客户端程序也越来越多。在当今越来越复杂 的应用环境中,我们的客户端程序不可避免的要同时进行多 任务的处理。一个优异的客户端程序 都会允许用户同时启动多个任务,从而大大提高用户的工作中实现多任效率以及用户体验。本文中我们来谈谈 Eclipse务的方式。在我们基于Eclipse 的 Java 程序中, 我们有很多种方式提供多任务的实 现。熟悉 Java 的朋友立即会想到 Java 的 Thread 类,这

2、是Java 中使用最多的中的 Job 是对 Java个实现多任务的类。 Eclipse 平台为多任务处理提供了自 己的API,那就是Job以及UlJob oEclipseThread 的一个封装, 为我们实现多任务提供了更方便的接口。以下是 Job 的基本用法:清单 1. Job 用法示例 Job job = newJob( “Job Name”) protected IStatus run(IProgressMonitor monitor) / 在这里添加你的任务代码return Status.OK_STATUS;中我们也会经常用到job.schedule(delayTime); 在 Ecl

3、ipseDisplay.asynchExec()和 Display.synchExec() 来启动任务的执行。 这两个方法主要 为了方便我们完成界面操作的任务。以下是Display.asynchExec() 的用法, Display.synchExec() 和它类 似。清单 2. Display.synchExec() 用法示例Display.getDefault().asyncExec(new Runnable() public void run() / 在这里添加你的任务代码个 Job接口来实现多任务, 而不是使用 Java 的 thread 。为什么呢? 主要有以下几个原因: Job 是

4、可重用的工作单元, 我们可以很方便的让它多次执行。 Job 提供了方便的接口, 使得我们在处理中能够很方便的与外界交流,报告当前的执 行进度 Eclipse 提供了相应的机制使得程序员可以方便的介 入 Job 的调度, 例如我们可以方便的实现每次只有一个同 类型的 Job 在运行 Eclipse 缺省提供了 Job 管理的程序,可 以查看当前所有的 Job 和它们的进度,也提供 UI 终止、暂用 Job 可以提高程序的性能,节省线程创建和销毁的开销。Eclipse中的 Job 封装了线程池的实现。 当我们启动一个 Job时, Eclipse 不会马上新建一个 Thread ,它会在它的线程池中

5、寻找是否有空闲的线个 Job 终止时,它所对应的线程 也不会立即终止,它会被返回到线程池中以备重复利用。这样,我们可以节省创建和销毁线程的开销下面我们从几个方中 Job 的实现 Eclipse的核心包中提供了一个 JobManager 类,它实现了现的。用 Job 的 schedule 方法后,这个 Job 会被 JobManager 首 先放到一个Job 运行的等待队列中去。之后, JobManager 会通知线程 池有新的 Job 加入了运行等待队列。 线程池会找出一个空闲 的线程来运行 Job ,如果没有 从上面 Job 运行的过程我们可以看到, JobManager 介入了个 Job

6、运行的全过程, 它了解 Job 什么时候开始, 什么时 候结束,每一时候 Job 的运行状态。 JobManager 将这些 Job 运行的信息以接口的方式度等,从而我们拥有了更加强大的控制 Job 的能力。为了我们更方便的了解 Job 所处的状态, JobManager 设置Job 的一个状态标志位 ,我们可以通过 Job 的 getState 方法获得 Job 当前的状态值以了解其状态:NONE :当一个 Job 刚构造的时候, Job 就会处于这种状态。当一个 Job 执行完毕(包括被取消)后, Job 的状态也会变回这种状态。WAITING:当我们调用了 Job的shedule方法,的

7、状态会变为 RUNNING 。 SLEEPING:当我们调用 Job 的 sleep 方法后, Job 会变成这一状态。也会转入这一状态,在这我们可以眠状态, Job 在这种状态中时不能马上转入运行。Job 唤醒。这样, Job 又会转入 WAITING 状态等待运行。外,在 Eclipse 的线程处理中, 有一个 UI 线程的概念。 Eclipse程序中的主线程是一个特殊的线程,程序启动后会先执行这 个线程,也就是我们的main() 函数所在的线程。作为桌面应用程序,我们的主线程 主要负责界面的响应以及绘制界面元素,所以通常我们也叫 它 UI 线程。 以下代码, 编过 SWT 应用程序的读者

8、会非常熟 悉。它一般出现在 main 函数的结尾。下面来仔细分析一下它的详细情况。 / 当窗口未释放时 中没有了等待的事件,就让该线程进入等待状态if (!display.readAndDispatch()display.sleep(); 上面的程序实际上就是我们 UI 线程的处理逻辑: 当程序启动后, UI 线程会读取事件等待队列, 看有没有事件等待处理。如果 有,它会进行相应处理,如果没有它会进入睡眠状态。如果 有新的事件到来,它又会被唤醒,进行处理。 UI 线程所需要 处理的事件包括用户的鼠标和键盘操作事 件,操作系统或程序中发出的绘制事件。一般来说,处理事 件的过程也就是响应用户操作的

9、过程。一个好的桌面应用程 序需要对用户的操作作出最快的响应,也就是说我们的 UI 线程必须尽快的处理各种事件。从我们程序的角度来说,在 UI 线程中我们不能进行大量的 计算或者等待,否则用户操作事件得不到及 时的处理。 通常,如果有大量的计算或者需要长时间等待 (例 如进行网络操作或者数据库操作)时,我们必须将这些长时 间处理的程序单独开辟出一个线程来执行。这样虽然后台运行着程序,但也不会影响界面上的操作。除主线程之外的所有线程都是非 UI 线程。UI 线程中来执行,否则会抛出 Exception ,所以我们要区分中执行。如何判断当前线程是否 UI 线程 :并发运行对于某些 Job ,为了避免

10、并发性问题,我们希望同时只有一个这样的 Job 在运行, 这时我们需要控制 Job 的并发运行。 在另一种情况下,我们也需要控制 Job的并发运行:我们在程序中对于一个任务,我们有可能会启是如果我们预测可能会同时有大量的任务, 如果每一个任务启动一个 Job ,我们同时启动的 Job 就会非 常多。这些 Job 会侵占大量的资源,影响其他任务的执行。简单我们可以使用 Job 的 rule 来实现控制 Job 的并发执行。private ISchedulingRule Schedule_RULE = newISchedulingRule() public boolean contains(ISc

11、hedulingRule rule) return this.equals(rule);public boolean isConflicting(ISchedulingRule rule) rulereturn this.equals(rule);对于需要避免同时运行的 Job ,我们可以将它们的 设成上面定义的 rule 。如:myjob1.setRule(Schedule_RULE);myjob2.setRule(Schedule_RULE); 这样对于 myjob1 和myjob2 这两个 Job ,它们不会再同时执行。 Myjob2 会等待myjob1 执行完再执行。 这是由 Ecli

12、pse 的 JobManager 来提中,任意供实现的。 JobManager 可以保证所有启动的 Job我们在上面定义的 rule 是最简单的。我们可以重写isConflicting 函数来实现一些更加复杂的控制,比如控制同 时同类型的 Job 最多只有指定的个数在运行。但是我们要注意, isConflicting 方法不能过于复杂。一旦 个 Job 的 rule 与其他 Job 的 rule 有冲突, isConflicting 方法 会调用很多次。如果其中的计算过于复杂,会影响整体的性 能。根据需要执行 Job 由 于我们有的 Job 有可能不是立即执行的,在有些情况下,等 到该 Job

13、 准备执行的时候, 该 Job 所要执行的任务已经没有 意义了。这时,我们可以使用 Job 的shouldSchedule ()和 shouldRun ()来避免 Job 的运行。在我们定义一个 Job 时,我们可以重载 shouldSchedule 和shouldRun 方法。在这些方法中,我们可以检查 Job 运行的些先决条件, 如果这些条件不满足, 我们就可以返回 false 。JobManager 在 安排 Job 运行时,它会先调用该 Job 的 shouldSchedule 方 法,如果返回为 false , JobManager 就不会再安排这个 Job运行了。同样, JobMa

14、nager 在真正启动一个线程运行一个 Job 前, 它会调用该 Job 的 shouldRun 方法,如果返回 false ,它不 再运行这个Job 。在下面的例子中,我们希望启动一个 Job 在十秒钟之义的,我们需要确保我们要更新的文本 框没有被销毁,我们重载了 shouldSchedule 和 shouldRun方法。 Text text = new Text(parent,SWT.NONE);更新界面” )UIJob refreshJob = new UIJob(public IStatus runInUIThread(IProgressMonitor monitor) return

15、Status.OK_STATUS;public boolean shouldSchedule()return !text.isDisposed();public boolean shouldRun()return !text.isDisposed();refreshJob.schedule(10000); 在 UI 线程中涉及长时间处理 的任务我 们经常碰到这样一种情况:用户操作菜单或者按钮会触发查 询大量数据,数据查询完后更新表格等界面元素。用户点击 菜单或者按钮所触发的处理程序一般处于 UI放到单独的 Job 中执行,一旦数据查询完毕,我们又必须更 新界面,这时我们又需要使用 UI 线程进

16、 行处理。下面是处理这种情况的示例代码:button.addSelectionListener(new SelectionListener()public void widgetSelected(SelectionEvent e)perform();public void widgetDefaultSelected(SelectionEvent e)perform(); private void perform()protected IStatus run(IProgressMonitor monitor)/ 在此添加获取数据的代码Display.getDefault().asyncExec(

17、newRunnable()public void run()/ 在此添加更新界面的代码); );延时执行 Job, 避免无用的 Job 运行我们经常需要根 据选中的对象刷新我们部分的界面元素。如果我们连续很快 的改变选择,而每次刷新界面涉及到的区域比较大时,界面会出现闪烁。从用户的角度来说,我们很快的改变选择,希的。在addPostSelectionChangedListener 方法。如果我们使用这 个方法监听selectionChanged 事件,当用户一直按着方向键改变选中时, 我们只会收到一个 selectionChanged 事件。这样我们可以 避免过度的刷新界面。实际上, Jfac

18、e 中就是通过延时执行 Job 来实final static Object UPDATE_UI_JOBFAMILY = newObject();tableviewer. addSelectionChangedListener (newpublic voidISelectionChangedListener () selectionChanged(SelectionChangedEvent event)Job.getJobManager().cancel(UPDATE_UI_JOBFAMILY);new UIJob( 更新界面 ) protected IStatus runInUIThread(

19、IProgressMonitor monitor) /更新界面return Status.OK_STATUS;public booleanbelongsTo(Object family)return family= UPDATE_UI_JOBFAMILY;.schedule(500);时我们将 Job 延时 500 毫秒执行(我们可以根据需要改变 延时的时间) 。如果下一个 selectionChanged 事件很快到来, 我们的调用Job.getJobManager().cancel(UPDATE_UI_JOBFAMILY)以前未运行的 Job 取消,这样只有最后一个 Job 会 真正运行。

20、在 UI 线程中等待非 UI 线程的结束有 时,我们在 UI 线程中需要等待一个非 UI 线程执行完,我们 才能继续执行。例如,我们在 UI 线程中要显示某些数据,但是这些数据又需要从数据库或者远程网络 获取。于是,我们会启动一个非 UI 的线程去获取数据。而 我们的 UI 线程必须要等待这个非 UI 线程执行完成,我们才 能继续执行。当然,一种简单的实现方法是 使用join。我们可以在UI线程中调用非UI线程的join方法, 这样我们就可以等待它执行完了,我们再继续。但是,这会 有一个问题。当我们的 UI 线程等待时,意味着我们的程序不会再响应界面操作,也不会刷的 run 方法来运行(如下)

21、 。 ModalContext 会将你的任务放 到一个独立的非UI 线程中执行, 并且等待它执行完再继续执行。 与 join 方法 不同的是,ModalContext在等待时不会停止 UI事件的处理。这样我们的程序就不会 没有响应了。 try ModalContext.run(new IRunnableWithProgress()public void run(IProgressMonitor monitor)throws InvocationTargetException,InterruptedException /*需要在非 UI 线程中执行的代码 */, true, new NullPr

22、ogressMonitor(),Display.getCurrent(); catch (InvocationTargetException e) catch (InterruptedException e) 针对相关联的 Job 统一进行处理有时,我们需要对相关联的 Job 一起处理。例如需要同时取消 这些 Job ,或者等待所有这些 Job 结束。这时我们可以使用JobFamily 。对于相关联的 Job ,我们可以将它们设置成同一个JobFamily 。我们需要重载 Job 的 belongsTo 方法以设置一个Job 的 Job Family。Private Object MY_JOB

23、_FAMILY = newObject();protected IStatus run(IProgressMonitor monitor) / 在这里添加你的任务代码return Status.OK_STATUS;public boolean belongsTo(Object family)return MY_JOB_FAMILY.equals(family);我们可以使用 JobManager 的一系列方法针对 Job Family进行操作:Job.getJobManager().cancel(MY_JOB_FAMILY);/取消所有属于 MY_JOB_FAMILY 的所有 JobJob.g

24、etJobManager().join(MY_JOB_FAMILY); / 等待属于MY_JOB_FAMILY 的所有 Job 结束Job.getJobManager().sleep(MY_JOB_FAMILY); / 将所有 属于 MY_JOB_FAMILY 的 Job 转入睡眠状态Job.getJobManager().wakeup(MY_JOB_FAMILY); / 将所 有属于 MY_JOB_FAMILY 的 Job 唤醒线程死锁的调试和解 决技巧 旦我们使用了线程,我们的程序中就有可能有死锁的发生。旦发生死锁,我们发生死锁的线程会没有响应,导致我们 程序性能下降。如果我们的 UI 线

25、程发生了死 锁,我们的程序会没有响应,必须要重启程序。所以在我们 多线程程序开发中,发现死锁的情况,解决死锁问题对提高 我们程序的稳定性和性能极为重要。如果我们发现程序运行 异常(例如程序没有响应) ,我们首先要确定是否发生了死锁。通过下面这些步骤,我们可以确定是否死锁以及死锁的Threadmain ),选择菜单 Run-Suspend 。这时 Eclipse会展开主线程的函数调用栈,我们就可以看到当前主线程正 在执行的操作。通常, Eclipse 在等待用户的操作,它的函 数调用栈会和以下类似: 图片示例如果主线程发生死锁,函数调用栈的最上层一般会 是你自己的函数调用,你可以查看一下你当前的

26、函数调用以 确定主线程在等待什么使用同样的方法查看其他线程,特别 是那些等待 UI 线程的线程我们需要找出当前线程相互的等 待关系,以便找出死锁的原因。我们找出死锁的线程后就可 以针对不同情况进行处理:减小锁的粒度,增加并发性调整 资源请求的次序将需要等待资源的任务放到独立的线程中 执行 Job 使用中要注意的问题不 要在 Job 中使用 Thread.sleep 方法。如果你想要让 Job 进 入睡眠状态,最好用 Job 的 sleep 方法。虽然,使用Thread.sleep 和中 JobJob 的 sleep 方法达到的效果差不多,但是它们实现的方式 完全不同, 对系统的影响也不一样。

27、我们知道 Eclipse是由 Eclipse 的JobManager 来管理的。如果我们调用 Job 的 sleep 方法,JobManager 会将 Job 转入睡眠状态,与其对应的线程也会 重新放入线程池等待运行其他 Job 。而如果我们在 Job 中直接调用Thread.sleep 方法, 它会直接使运行 Job 的线程进入睡眠状 态,其他 Job 就不可能重用这个线 程了。同时,虽然运行该 Job 的线程进入了睡眠状态, Job的状态还是 Running (运行状态) ,我们也不能用 Job 的wakeup 方法唤醒该 Job 了 Job方法,Job就会停止运行。实际上,这并不一定正确

28、,当Job 处于不同的状态时,我们调用Job 的 cancel 方法所起的效果是不同的。 当 Job 在 WAITING法,JobManager 会将 Job 直接从等待运行的队列中删除, 不会再运行了, 这时 cancel 方法会返回 true 。但是如果cancel 方法调用并不会立即终止 Job 的运行, 它只会设定一个标志,指明这个 Job 已经被取消了。 我们可以使用 Job的 run 方法传入的参数IProgressMonitor monitor ,这个参数的 isCanceled 方法会返回 Job 是否被取 消的状态。如果需要,我们必须在我们的代码的适当位置检 查 Job 是否

29、被取消的标不一定立即终止 Job ,如果我们需要等待被取消的 Job 运行 完再执行,我们可以用如下代码:if (!job.cancel() job.join();Join 方法的使用。 由于 join 方法会导致一个线程等 待另一个线程,一旦等待线程中拥有一个被等待线程所需要 的锁,就会产生死锁。当我们的线程中需要用到同步时,这 种死锁的情况非常容易出现,所以我们使用 join 时必须非常 小心,尽量以其他方法替代。避 免过时的 Job 造成的错误。 由于我们启动的线程并不一定是 马上执行的,当我们的 Job 开始运行时,情况可能发生了变 化。我们在 Job 的处理代码中要考虑到 这些情况。

30、一种典型的情况是,我们在启动一个对话框或者 初始化一个 ViewPart 时,我们会启动一些Job 去完成一些数据读取的工作,一旦数据读取结束,我们 会启动新的 UIJob 更新相应的 UI 。有时,用户在打开对话框或者 View 后,马上关闭了该对话框或者 View 。这时我们启动的线程并没有 新 UI ,就会出错。在我们的代码中必须作相应的处理。 所以, 我们在线程中更新界面元素之前,我们必须先检查相应的控 件是否已经被 dispose 了结束语在我们进行基于 Eclipse 的 客户端开发时,使用多线程可以大大的提供我们的程序并发 处理能力,同时对于提高用户体验也有很好的帮助。但是, 多线程程序也有其不利的一面, 我们也不要滥用线程: 首先, 多线程程序会大大的提高我们程序的复杂度,使得我们的开 发和调试更加困难其次,过多的线程容易引发死锁、数据同 步等并发问题的发生另外,由于线程创建和销毁需要开销, 程序的整体性能可能因为过多线程的使用而下降所以,我们 在使用线程时一定要谨慎。本文对 Eclipse 线程的讨论,希 望能对大家使用线程有所帮助。由于实际情况较为复杂,文 中所提到的方法仅供参考,读者对于不同的实际问题需要进 行具体分析,从而找出最佳的解决方案。参考资料 查看developerWorks博客的最新信息。

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1