jAVA2程序设计基础第十一章.ppt

上传人:max****ui 文档编号:6357392 上传时间:2020-02-23 格式:PPT 页数:23 大小:375KB
返回 下载 相关 举报
jAVA2程序设计基础第十一章.ppt_第1页
第1页 / 共23页
jAVA2程序设计基础第十一章.ppt_第2页
第2页 / 共23页
jAVA2程序设计基础第十一章.ppt_第3页
第3页 / 共23页
点击查看更多>>
资源描述
第11章多线程 教学提示 在同时处理多个任务的应用中 多线程的意义显得尤其重要 本章将介绍多线程的内容 主要包括线程的概念 线程的创建 线程间的同步与通信 以及线程的生命周期和状态控制 并说明使用多线程时应该注意的问题 学习完本章之后 读者将对Java多线程机制有一个全面的了解 教学目标 理解线程的概念 熟练掌握线程的创建 线程间的同步与通信 以及线程的生命周期和状态控制 并牢记使用多线程时应该注意的问题 11 1线程的概念 在介绍线程前有必要简要介绍一下进程 这将有助于读者理解线程概念 相信大多数读者都知道 在Windows操作系统中可以同时执行多个程序 比如打开一个资源管理器和多个IE浏览器 同时使用播放器播放音乐 后台可能同时还有杀毒软件防火墙在运行 这里的每一个运行的程序都是一个进程 严格地说 这种说法是不准确的 程序一般是指保存在外部存储器 一般为硬盘 中的代码文件 当程序被执行时 系统会先在内存中为其分配一块空间 再把其代码复制到该空间中执行 这个在由系统分配的内存空间中执行的程序才是进程 一个程序可能同时存在多个相应的进程 如同时打开多个IE浏览器 每一个浏览器窗口都是一个进程 都拥有自己独立的内存空间 而它们都来自于同一个程序 11 2线程的创建 对于一个用Java编写的进程来说 在Java虚拟机启动之初 会且只会产生一个独一的非守护线程 守护线程将在稍后介绍 具有代表性的是类中静态方法main 产生的线程 该线程为主线程 可以创建和控制其他线程 11 2 1继承自类Thread 11 2 2实现接口Runnable 11 2 3两种创建线程方式的对比 11 2 4守护线程Daemon 11 2 1继承自类Thread 类Thread位于java lang包中 由于java lang包被自动包含入每个Java文件中 所以可以直接使用类Thread而无需编写import语句 返回 11 2 2实现接口Runnable Runnable接口非常简单 其全貌如下 publicinterfaceRunnable voidrun 返回 11 2 3两种创建线程方式的对比 Thread是Java已经严格封装好了的类 在面向对象思想中 继承这样的类并修改或扩充它不是十分可取的 因为可能会出现人为失误 对一个类进行继承修改或扩充 将可能导致该子类出现不可预料的错误 返回 11 2 4守护线程Daemon 线程分为用户线程和守护线程两种 用户线程即一般线程 守护线程是具有如下特性的线程 它会在所有用户线程 即非守护线程 结束之后立即被Java虚拟机结束 而不管其是否已执行完毕 从而结束整个进程 守护线程往往处于无限循环中 用于监听其他线程 一般是用户线程 也可以是其他守护线程 的运行 并提供某种通用性的服务 典型的如Internet中收发E mail邮件的服务 通过线程对象的isDaemon 方法可以判断该线程是否为守护线程 通过setDaemon 方法可以改变该线程的类型 setDaemon false 将线程改为用户线程 setDaemon true 将线程改为守护线程 该方法必须在调用线程的start 方法前调用才有效 否则线程将为默认的线程类型 由用户线程创建的线程默认为用户线程 由守护线程创建的线程默认为守护线程 main 方法产生的主线程始终为用户线程 返回 11 3线程的同步 在单线程的进程中 一个进程一次只能执行一个任务 一次只能使用一个资源 不需要考虑两个或更多个任务同时试图使用同一个资源的问题 如两个任务同时修改同一个数据 或同时进行打印操作而只有一台打印机 然而在多线程环境下 这种多个线程试图同时使用相同且有限的资源的情况 是很有可能发生的 若不提供某种机制避免这种情况的出现 后果将可能是非常严重且不可预料的 如造成某些线程数据的不一致 使某些线程陷入无限循环永远无法退出 破坏某些关键文件或数据库中的重要数据 11 3 1资源冲突 11 3 2同步机制 11 3 3同步效率 11 3 1资源冲突 这是一段完整可编译的代码 提供了reduceMainData 方法用于递减私有的主数据 在run 方法中保存主数据与打印主数据之前进行了多达1024000次的浮点运算用于延缓线程运行 这将使得该线程在此处很可能被暂停 此时若main 主线程被调度到CPU执行 它很可能会递减该线程的主数据 从而造成打印时主数据与备份数据的不一致 返回 11 3 2同步机制 我们永远无法知道线程什么时候开始执行 并不是在创建它的时刻 它便开始执行的 也无法知道它什么时候会被暂停 更加无从得知在暂停期间其他线程会对它进行怎样的访问控制 这是多线程环境下线程的根本性质 由此产生的资源冲突问题是代码编写者必须考虑的 至少在重要的时刻必须避免关键资源的冲突 返回 11 3 3同步效率 为避免可能的资源冲突 将线程中所有除run 外的方法都声明为synchronized似乎是个可行的方法 然而获得一个线程对象的锁的代价非常高 至少是一般方法调用 仅仅是方法的进入和退出 不包括方法的执行体 的四倍 因此将那些不会造成资源冲突的方法的关键字synchronized省去 是非常有利的 但单纯为了提高性能而省去某个方法的关键字synchronized可能带来灾难性的后果 又是不可取的 究竟哪些方法应该声明为synchronized 哪些方法不应该声明为synchronized 并没有一个统一的标准 返回 11 4线程间的通信 线程不仅仅作为单独的个体存在 它往往需要与其他线程进行数据交互 这种数据的交互便是线程间的通信 通过一些简单的方式可以实现线程间的通信 例如 在线程类中设置一个静态 static 变量 它可以作为所有由该类生成的线程的共享数据 11 2节的几个实例中递减计数count就是这样一个共享数据 或者在线程类中设置一个私有 private 变量 并提供读取和修改该变量的公有 public 方法 其他线程可以通过这两个方法访问由该类生成的线程的数据 然而这样只能实现一些简单且数据量较少的线程间的通信 并有可能造成Java同步机制无法避免的资源冲突问题 特别是设置静态共享数据时 因此有必要提供一种安全高效的线程间的通信机制 这便是在介绍I O系统时曾经提到过的管道流PipedInputStream PipedOutputStream和PipedReader PipedWriter 它们正是被设计用来实现多线程环境下线程间的通信的 返回 11 5线程的控制 多个线程不能同时占用一个CPU运行 具体什么时间让哪个进程占用CPU运行 以及运行多长时间 其调度控制非常复杂 这些控制是由Java虚拟机的线程调度程序自动完成的 然而某些时候 我们希望能自己控制线程的运行 例如编写提供某种服务的守护线程时 往往必须对某些线程的运行进行控制 Java为此提供了线程的控制机制 11 5 4控制线程的状态 11 5 1线程的状态 11 5 2线程的优先级 11 5 3线程的生命周期 11 5 1线程的状态 控制线程的运行实际上就是控制线程的状态 让线程在不同的状态间切换 线程有如下5种基本状态 1 新生 New 2 可运行 Runnable 3 运行 Running 4 死亡 Dead 5 阻塞 Blocked 返回 11 5 2线程的优先级 在同时有多个线程处于可运行状态等待运行时 应该让哪个线程占用CPU 是由线程调度程序决定的 我们无法直接干预 然而 通过设置线程的优先级 可以影响调度程序的调度 线程的优先级类似于运算符的优先级 优先级最高的线程会被调度程序最先调入CPU运行 对于具有同样优先级的线程 将按照先进先出 IFIO 的原则 哪个线程先进入可运行状态等待CPU 哪个线程先运行 但这并不意味着优先级较低的线程一定要在优先级较高的线程结束后才能运行 优先级低的线程只是获得CPU的机会较少而已 返回 11 5 3线程的生命周期 所谓线程的生命周期 是指线程从创建之初到运行完毕的过程 就像人的整个生命周期从出生 经过童年 少年 青年 中年 老年 直到去世一样 线程的整个生命周期就是在各种状态间切换的 返回 11 5 4控制线程的状态 事实上 此前我们已经进行了一些线程的控制 如调用start 方法将线程从新生状态转为可执行状态 调用yield 方法将线程转为阻塞状态 也可以通过在run 方法中调用return语句将线程从运行状态转为死亡状态 在这些线程的状态间切换中 从可运行状态转为运行态只能由调度程序控制 通过设置线程优先级可以稍加干预 从新生状态转为可执行状态和从运行状态转为死亡状态很简单 而从运行状态到阻塞状态或可运行状态 以及从阻塞状态到可运行状态的切换 才是我们真正感兴趣的 也是控制线程状态的重点 返回 11 6使用多线程应注意的问题 本节将讲述几个在Java多线程应用中应该特别注意的问题 11 6 4不建议使用的方法 11 6 1多线程的效率 11 6 2饿死 11 6 3死锁 11 6 1多线程的效率 多线程的优点是显而易见的 它使得我们可以同时处理多个任务 可以通过守护线程在后台提供某种通用性的服务 可以监视某种情况的发生等等 它的目的是让我们更有效地运用计算机资源 特别是其中最重要的CPU资源 这一优点在多CPU系统中尤其突出 这其中最经典的例子就是 在一个线程等待I O操作期间 让其他线程占用CPU运行 以提高CPU的利用率 返回 11 6 2饿死 在介绍线程优先级时曾提及 优先级较低的线程不是只能在优先级较高的线程结束后才能运行 优先级低的线程只是获得CPU的机会较少 Java虚拟机的调度程序保证每个线程都能运行 这看来似乎并没有问题 然而调度程序的这种保证并没有时间限制 也就是说它不能保证在一个可以预见的时间范围内 让优先级低的线程一定能运行 没人愿意看到一个线程在等待CPU一个小时后 仍没有得到运行机会的情况出现 这种低优先级线程在较长时间内无法获得运行机会的现象就是所谓的 饿死 返回 11 6 3死锁 所谓独占性资源是指被一个线程占用后 除非该线程放弃 否则其他线程不能抢占的资源 也可以理解为同时只能完成一个任务的资源 CPU就是典型的独占性资源 其他如打印机 软盘等大部分I O设备也都是独占性资源 返回 11 6 4不建议使用的方法 Thread中的方法stop suspend 和resume 是Java2不建议使用的 返回 11 7上机指导 在本次上机指导中 将给出一个计时器实例 针对前面几节中的内容进行实际上机练习 目的是让读者了解多线程在实际中的应用 并进一步熟悉线程的控制 通过理解该例 读者将会具备基本的多线程编程能力
展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 图纸专区 > 课件教案


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!