多线程ppt课件

上传人:钟*** 文档编号:4478268 上传时间:2020-01-08 格式:PPT 页数:66 大小:918KB
返回 下载 相关 举报
多线程ppt课件_第1页
第1页 / 共66页
多线程ppt课件_第2页
第2页 / 共66页
多线程ppt课件_第3页
第3页 / 共66页
点击查看更多>>
资源描述
7 Java多线程 1 内容 多线程基本概念Java多线程创建多线程线程的状态控制Java多线程的一些问题小结注 本课件部分材料来自网络 2 1多线程基本概念 文件 输入输出装置 各种系统资源 数据区段 程序区段 只有一个地方在执行 文件 输入输出装置 各种系统资源 程序区段 同时有数个地方在执行 传统的进程 多线程的任务 3 多线程的优势 减轻编写交互频繁 涉及面多的程序的困难程序的吞吐量会得到改善由多个处理器的系统 可以并行运行不同的线程 否则 任何时刻只有一个线程在运行 形成并发运行 4 线程与进程的区别 多个进程的内部数据和状态都是完全独立的 而多线程是共享一块内存空间和一组系统资源 有可能互相影响线程本身的数据通常只有寄存器数据 以及一个程序执行时使用的堆栈 所以线程的切换比进程切换的负担要小 5 多线程编程原则 安全性 如果两个以上的线程访问同一对象时 一个线程会损坏另一个线程的数据 这就违反了安全性原则可行性 如果仅仅实现了安全性 程序却在某一点后不能继续执行或者多个线程发生死锁 那么这样的程序也不能作为真正的多线程程序来应用高性能 多线程的目的是为了增加程序运行的性能 6 2 Java线程概念 对线程的综合支持是Java技术的一个重要特色 它提供了thread类 监视器和条件变量的技术 虽然许多操作系统支持多线程 但若要用C或C 编写多线程程序是十分困难的 因为它们对数据同步的支持不充分 7 线程对象和线程的区别 线程对象是可以产生线程的对象比如在java平台中Thread对象 Runnable对象 线程 是指正在执行的一个指令序列 在java平台上是指从一个线程对象的start 开始 运行run方法体中的那一段相对独立的过程 8 思考如果我们成功编译了该java文件 然后运行发生的过程 Jvm进程启动 JVM产生一个主线程还有一些其它线程 例如垃圾回收等 classBeginClass publicstaticvoidmain String args for inti 0 i 100 i System out println Hello World 9 剖析多线程程序 classMyThreadextendsThread publicvoidrun System out println Threadsay Hello World publicclassMoreThreads publicstaticvoidmain String args newMyThread newMyThread start System out println Mainsay Hello World 10 3 创建多线程 Runnable与Thread1 publicclassmythreadextendsAppletimplementsRunnable 小应用或已经是某个类的子类时 2 继承类ThreadpublicclassmythreadextendsThread创建方法 newthread newThread this newthread start 11 Runable与Thread的区别使用runable最主要的原因是 java缺少多重继承的机制 可能你的类已经继承了其他类了 这时你无法继承自thread类 只能用runnable了Runable创建的线程共享数据区 12 publicclassTest publicstaticvoidmain String args throwsException MyThreadmt newMyThread mt start mt join Thread sleep 3000 mt start 输出 Exceptioninthread main java lang IllegalThreadStateException说明 通过Thread实例的start 一个Thread的实例只能产生一个线程 classRimplementsRunnable privateintx 0 publicvoidrun for inti 0 i 100 i try Thread sleep 10 catch Exceptione System out println x publicclassTest publicstaticvoidmain String args throwsException Rr newR for inti 0 i 10 i newThread r start 14 packagedebug importjava io importjava lang Thread classMyThreadextendsThread publicintx 0 publicvoidrun System out println x classRimplementsRunnable privateintx 0 publicvoidrun System out println x publicclassTest publicstaticvoidmain String args throwsException for inti 0 i 10 i Threadt newMyThread t start Thread sleep 10000 让上面的线程运行完成Rr newR for inti 0 i 10 i Threadt newThread r t start 15 重要的方法 start 从CPU中申请另一个线程空间来执行run 方法中的代码run 是运行线程的主体 启动线程时 由java直接调用publicvoidrun 如果你不调用Start 直接调用run 会如何 stop 停止线程 调用线程的newthread stop 不是安全的处理 sleep方法暂停线程的执行 让其它线程得到机会 sleep要丢出异常 必须抓住 Try sleep 100 catch InterruptedExceptione 16 importjavax swing publicclassApplet1extendsJApplet mythreadt1 newmythread publicvoidinit t1 start classmythreadextendsThread publicvoidrun for inti 0 i 4 i System out println i try sleep 400 catch InterruptedExceptione 17 7 2创建线程的方式 importjavax swing importjava awt publicclassApplet1extendsJApplet Ct1 newC this publicvoidinit t1 start publicvoidpaint Graphicsg g drawString Hello java 10 50 classCextendsThread Applet1a C Applet1b a b publicvoidrun while true a repaint try sleep 400 catch InterruptedExceptione 18 join 等待线程执行完毕 被等待的那个线程不结束 当前线程就一直等待 publicclassTest publicstaticvoidmain String args throwsException MyThreadmt newMyThread mt start mt join System out println 101 19 其它常用的方法isAlive 判断线程目前是否正在执行状态中if newthread isAlive newthread stop resume 要求被暂停线程继续执行suspend 暂停线程的执行yield 将执行的权力交给其它线程 自己到队列的最后等待 20 线程的优先权某一时刻只有一个线程在执行 调度策略为固定优先级调度 newthread setPriority Thread MIN PRIORITY 级别有 MIN PRIORITYNOM PRIORITYMAX PRIORITY自私的线程 有很高的优先权的线程 不主动睡眠或让出处理器控制权 21 4 线程的状态控制 线程的状态 22 当一个线程执行完所有语句后就自动终止调用线程的stop 方法 也可以强制终止线程 可能产生不完整的残废数据 如果希望线程正常终止 可采用标记来使线程中的run 方法退出 23 publicclassXyzimplementsRunnable privatebooleantimeToQuit false publicvoidrun while timeToQuit cleanupbeforerun ends publicvoidstopRunning timeToQuit true 24 publicclassControlThread privateRunnabler newXyz privateThreadt newThread r publicvoidstartThread t start publivoidstopThread r stopRunning 25 暂停线程的执行等待条件满足再执行下面的例子显示线程的挂起和唤醒Applet第一次开始时 线程被启动浏览器改变页面时 小应用程序的stop 方法被调用 线程被挂起 浏览器回到原来的页面时 线程被唤醒 26 publicvoidstart if mythread null mythread newThread mythread start else mythread resume publicvoidrun while true try sleep 100 catch InterruptedExceptione publicvoidstop mythread suspend 27 5 Java多线程问题 执行顺序多个线程运行时 调度策略为固定优先级调度 级别相同时 由操作系统按时间片来分配下面给出的例子中 共运行三个线程 它们做同样的事 每次打印循环次数和自己的序列号 运行结果表明 它们并不是连续运行的 如果给某个线程赋予较高的优先权 则发现这个进程垄断控制权thread setPriority Thread MAX PRIORITY 28 7 3多线程问题 多个进程运行时执行顺序是交叉的publicclassMyThreadextendsThread intthreadNum publicstaticvoidmain Stringargs MyThreadarray newMyThread 3 for inti 0 i try sleep 1000 catch InterruptedExceptione System out println thread threadNum bye 29 如何写多线程 1 分别定义不同的线程类 在各自的run方法中定义线程的工作classmythread1extendsThread publicvoidrun classmythread2extendsThread publicvoidrun 2 在主类中实例化各线程类 并启动线程 publicclassdemoextendsApplet publicvoidinit mythreadt1 newmythread1 mythreadt2 newmythread2 t1 start t2 start 30 练习 将窗口分为上下两个区 分别运行两个线程 一个在上面的区域中显示由右向左游动的字符串 另一个在下面的区域从左向右游动的字符串 方法一 一个线程 在paint方法中使用两个输出字符串的语句publicvoidpaint Graphicsg ify1200y2 0elsey2 y2 10 g drawString hello Java 20 y1 g drawString hello Java 40 y2 31 方法二 定义两个类 运行各自的线程 各自有自己的paint 方法 注意 两个Applet必须是panel类或者是canvas类 将Applet的区域分成两块 否则不能运行paint语句 32 importjavax swing importjava awt publicclassApplet1extendsJApplet Ct1 t2 myCanvasc1 c2 ContainercontentPane getContentPane publicvoidinit c1 newmyCanvas c2 newmyCanvas contentPane setLayout newGridLayout 2 1 contentPane validate contentPane add c1 contentPane add c2 t1 newC c1 5 t2 newC c2 5 t1 start t2 start classmyCanvasextendsCanvas publicvoidpaint Graphicsg intx inty g drawString HelloWorld x y classCextendsThread myCanvasa intsteps intx C myCanvasb intsize a b steps size x 0 publicvoidrun while true x x steps if xa getWidth x 0 a repaint a paint a getGraphics x 50 try sleep 10 catch InterruptedExceptione 33 线程间的通信 1 线程间的通信可以用管道流 创建管道流 PipedInputStreampis newPipedInputStream PipedOutputStreampos newPipedOutputStream pis 或 PipedOutputStreampos newPipedOutputStream PipedInputStreampis newPipedInputStream pos 34 管道流不能直接读写PrintStreamp newPrintStream pos p println hello DataInputStreamd newDataInputStream pis d readLine 2 通过一个中间类来传递信息 35 管道流可以连接两个线程间的通信两个线程在运行 一个往外输出信息 一个读入信息 将一个写线程的输出通过管道流定义为读线程的输入 outStream newPipedOutputStream inStream newPipedInputStream outStream newWriter outStream start newReader inStream start 36 主类Pipethread 辅类Writer线程类 辅类Reader线程类 管道流 将数据写到输出流 从流中读数据 输入流 作为参数传给WriterWriter outStream 37 7 4多线程问题 线程间的通信 importjava io publicclassPipethread publicstaticvoidmain Stringargs PipethreadthisPipe newPipethread thisPipe process publicvoidprocess PipedInputStreaminStream PipedOutputStreamoutStream PrintStreamprintOut try outStream newPipedOutputStream inStream newPipedInputStream outStream newWriter outStream start newReader inStream start catch IOExceptione 38 7 4多线程问题 线程间的通信 classReaderextendsThread privatePipedInputStreaminStream publicReader PipedInputStreami inStream i publicvoidrun Stringline DataInputStreamd booleanreading true d newDataInputStream inStream while reading 39 7 4多线程问题 线程间的通信 classWriterextendsThread privatePipedOutputStreamoutStream privateStringmessages Monday Tuesday Wednsday Thursday Friday Saturday Sunday publicWriter PipedOutputStreamo outStream o publicvoidrun PrintStreamp newPrintStream outStream for inti 0 i messages length i p println messages i p flush System out println WrIte messages i try Thread sleep 4000 catch InterruptedExceptione p close p null 40 结果可能是 WrIte MondayRead MondayWrIte TuesdayRead TuesdayRead WednsdayWrIte WednsdayRead ThursdayWrIte ThursdayRead Friday WrIte Friday WrIte Saturday Read Saturday Read Sunday WrIte Sunday 41 资源协调 42 资源协调 43 对共享对象的访问必须同步 叫做条件变量 Java语言允许通过监视器 有的参考书称其为管程 使用条件变量实现线程同步 监视器阻止两个线程同时访问同一个条件变量 它如同锁一样作用在数据上 线程1进入withdrawal方法时 获得监视器 加锁 当线程1的方法执行完毕返回时 释放监视器 开锁 线程2的withdrawal方能进入 44 用synchronized来标识的区域或方法即为监视器监视的部分 一个类或一个对象有一个监视器 如果一个程序内有两个方法使用synchronized标志 则他们在一个监视器管理之下 一般情况下 只在方法的层次上使用关键区 45 此处给出的例子演示两个线程在同步限制下工作的情况 classAccount staticsintbalance 1000 staticsintexpense 0 publicsynchronizedvoidwithdrawl intamount if amount balance balance amount expense amount else System out println bounced amount 46 实例范围同步方法publicdclasssyncTest synchronizedvoidaMethod 需要同步使用的代码 synchronizedaMethod 可以防止多个线程同时访问这个对象实例的synchronized方法 如果一个对象有多个synchronized方法 只要一个线程访问了其中的一个synchronized方法 其它线程不能同时访问这个对象中任何一个synchronized方法 47 实例范围同步区块publicdclasssyncTest voidaMethod 无需同步使用的代码 synchronized this 需要同步使用的代码块 除了方法前用synchronized关键字 synchronized关键字还可以用于方法中的某个区块中 表示只对这个区块的资源实行互斥访问 用法是 synchronized this 区块 它的作用域是当前对象 48 类范围在类范围内使用synchronized也有同步方法和同步区块两种形式 类范围同步方法publicdclasssyncTest synchronizedstaticvoidaMethod 需要在类范围同步使用的代码 49 synchronizedstaticaStaticMethod 防止多个线程同时访问这个类中的synchronizedstatic方法 它可以对类的所有对象实例起作用 也就是说在一个JVM中 同一时间最多有一个该类的静态同步方法在执行 这样的方法可以应用到多线程的同步中 实现各线程直接的数据共享和互动 50 类范围同步区块publicdclasssyncTest staticvoidaMethod 无需同步使用的代码synchronized syncTest class 需要在类范围同步使用的代码 类范围同步区块功能与类范围同步方法相同 只是对一个区块的代码的同步 用法是 在static方法内加同步区块 sychronized 类名 class 区块 51 synchronized关键字是不能继承的 也就是说 基类的方法synchronizedf 在继承类中并不自动是synchronizedf 而是变成了f 继承类需要你显式的指定它的某个方法为synchronized方法 52 2 等待同步数据 可能出现的问题 生产者比消费者快时 消费者会漏掉一些数据没有取到消费者比生产者快时 消费者取相同的数据 notify 和wait 方法用来协调读取的关系 notify 和wait 都只能从同步方法中的调用 53 notify的作用是唤醒正在等待同一个监视器的线程 wait的作用是让当前线程等待信息版例子read 方法在读信息之前先等待 直到信息可读 读完后通知要写的线程 write 方法在写信息之前先等待 直到信息被取走 写完后通知要读的进程 54 writer reader aaaa bbbbb cccc aaaa aaaa aaaa aaaa aaaa aaaa bbbbb cccc cccc cccc cccc bbbbb cccc 55 publicclassWaitNotifyDemo publicstaticvoidmain String args MessageBoardm newMessageBoard Readerreadfrom m newReader m Writerwriteto m newWriter m writeto m start readfrom m start 56 7 3多线程问题 资源协调 classMessageBoard privateStringmessage privatebooleanready false publicsynchronizedStringread while ready false try wait catch InterruptedExceptione ready false notify returnmessage publicsynchronizedvoidwrite Strings while ready true try wait catch InterruptedExceptione message s System out println BoadGot s ready true notify 57 7 3多线程问题 资源协调 classReaderextendsThread privateMessageBoardmBoard publicReader MessageBoardm mBoard m publicvoidrun Strings booleanreading true while reading s mBoard read System out println Readerread s if s equals logoff reading false System out println Finished 10seconds try sleep 10000 catch InterruptedExceptione 58 7 3多线程问题 资源协调 classWriterextendsThread privateMessageBoardmBoard privateStringmessages Monday Sunday publicWriter MessageBoardm mBoard m publicvoidrun for inti 0 i messages length i System out println Writerwrote messages i mBoard write messages i try sleep int Math random 100 catch InterruptedExceptione System out println Writerwrote logoff mBoard write logoff 59 notifyAll 让等待某个对象K的所有线程离开阻塞状态 notify 随机地选取等待某个对象K的线程 让它离开阻塞状态sleep 方法是使线程停止一段时间的方法 在sleep时间间隔期满后 线程不一定立即恢复执行 这是因为在那个时刻 其它线程可能正在运行而且没有被调度为放弃执行 除非 a 醒来 的线程具有更高的优先级 b 正在运行的线程因为其它原因而阻塞 60 waite 和notify 因为会对对象的 锁标志 进行操作 所以它们必须在synchronized函数或synchronizedblock中进行调用 如果在non synchronized函数或non synchronizedblock中进行调用 虽然能编译通过 但在运行时会发生IllegalMonitorStateException的异常 61 多线程问题 资源的协调和锁定1 死锁问题如果你持有一个锁并试图获取另一个锁时 就有死锁的危险 解决死锁问题的方法 给条件变量施加排序 62 多线程问题 daemon线程 什么是daemon 守护 在客户 服务器模式下 服务器的作用是等待用户发来请求 并按请求完成客户的工作守护线程是为其它线程提供服务的线程守护线程一般应该是一个独立的线程 它的run 方法是一个无限循环 守护线程与其它线程的区别是 如果守护线程是唯一运行着的线程 程序会自动退出 客户端 服务器端 request daemon 63 调用isDaemon 可调查一个线程是不是一个DaemonsetDaemon 打开或者关闭一个线程的Daemon状态如果是一个Daemon线程 那么它创建的任何线程也会自动具备Daemon属性 64 小结 1 实现线程有两种方法 实现Ruannable接口继承Thread类2 在小应用中通常在start中创建线程3 当新线程被启动时 java调用该线程的run方法 它是Thread的核心 4 线程由四个状态 新生 运行 暂停 死亡 65 5 两个或多个线程竞争资源时 需要用同步的方法协调资源 6 多个线程执行时 要用到同步方法 即使用synchronized的关键字设定同步区7 wait和notify起协调作用8 守护进程的特点是当程序中只剩它自己时 会自动中止 66
展开阅读全文
相关资源
相关搜索

当前位置:首页 > 图纸专区 > 大学资料


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

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


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