购买

¥30.0

加入VIP
  • 专属下载特权
  • 现金文档折扣购买
  • VIP免费专区
  • 千万文档免费下载

上传资料

关闭

关闭

关闭

封号提示

内容

首页 第7章Java多线程机制

第7章Java多线程机制.ppt

第7章Java多线程机制

烟雨梦兮
2018-10-14 0人阅读 举报 0 0 0 暂无简介

简介:本文档为《第7章Java多线程机制ppt》,可适用于IT/计算机领域

Java多线程机制多线程程序设计的意义生命周期线程类的主要方法线程编程的方式守护线程线程同步概念线程死锁线程的协调与通讯Java语言的一个重要功能特点就是内置对多线程的支持它使得编程人员可以很方便地开发出具有多线程功能能同时处理多个任务的功能强大的应用程序方便地实现任务的并发处理。程序进程线程程序是为完成特定任务、用某种语言编写的一组指令的集合。指一段静态的代码。进程是程序的一次动态执行过程是系统进行调度和资源分配的一个独立单位。它对应了从代码加载、执行至执行完毕的一个完整过程这个过程也是进程本身从产生、发展至消亡的过程。基本概念之一:进程进程是正在运行的一个程序程序:静态对象--进程:动态过程操作系统为每个进程分配一段内存空间包括:代码、数据以及堆栈等资源多任务的操作系统(OS)中进程切换对CPU资源消耗较大例如你的机器装了一个QQ程序但是同时允许两个帐号登陆那此时有两个QQ进程运行。线程线程是比进程更小的执行单位,一个进程在其执行过程中可以产生多个线程形成多条执行线索每条线索即每个线程也有它自身的产生、存在和消亡的过程是一个动态的概念。线程的特点线程不能独立存在必须存在于进程中各线程间共享进程空间的数据。线程线程创建、销毁和切换的负荷远小于进程又称为轻量级进程(lightweightprocess)。进程与线程的关系由谁管理?线程由程序负责管理而进程由操作系统调度。线程依附于进程线程依附于进程的上下文环境中随进程或父线程执行后启动。地址空间多个线程使用相同的地址空间因此线程之间的通信非常方便。而进程之间使用不同的地址空间可以单独执行。基本概念之二:多线程多线程是指同时存在几个执行体按几条不同的执行线索共同工作的情况。多线程实现单个进程中的并发计算。各线程间共享进程空间的数据并利用这些共享单元来实现数据交换、实时通信与必要的同步操作。多线程的程序能更好地表述和解决现实世界的具体问题是计算机应用开发和程序设计的一个必然发展趋势。例如你上QQ后可以给甲传文件给乙视频聊天。那此时该QQ进程管理了两个线程。分别负责传文件和视频聊天。进程与多线程线程的调度调度策略时间片抢占式:高优先级的线程抢占CPUJava的调度方法同优先级线程组成先进先出队列使用时间片策略对高优先级使用优先调度的抢占式策略多线程程序设计是并发程序设计的一种各个线程之间是并行执行的当我们需要在一个程序当中同时执行几段代码时就需要用到多线程来实现。每个applicationJava程序都有一个隐含的主线程。Java应用程序总是从主类的main方法开始执行。当JVM加载代码发现main方法之后就会启动一个线程这个线程称作“主线程”该线程负责执行main方法。如果main方法中没有创建其他的线程那么当main方法执行完最后一个语句即main方法返回时JVM就会结束我们的Java应用程序。如果main方法中又创建了其他线程那么JVM就要在主线程和其他线程之间轮流切换保证每个线程都有机会使用CPU资源main方法即使执行完最后的语句JVM也不会结束我们的程序JVM一直要等到程序中的所有线程都结束之后才结束我们的Java应用程序线程的生命周期要想实现线程必须在主线程中创建新的线程对象。Java语言使用Thread类及其子类的对象来表示线程在它的一个完整的生命周期中通常要经历如下的五种状态:线程的生命周期新建:当一个Thread类或其子类的对象被声明并创建时新生的线程对象处于新建状态就绪:处于新建状态的线程被启动后将进入线程队列等待CPU时间片此时它已具备了运行的条件运行:当就绪的线程被调度并获得处理器资源时,便进入运行状态run()方法定义了线程的操作和功能阻塞:在某种特殊情况下被人为挂起或执行输入输出操作时让出CPU并临时中止自己的执行进入阻塞状态死亡:线程完成了它的全部工作或线程被提前强制性地中止stop()或destroy()线程的生命周期线程的生命周期(续)Newborn:线程已创建但尚未执行Runnable:(就绪)线程已被调度按优先级和先到先服务原则在队列中排队等待CPU时间片资源Runnnig:正在运行Blocked:(阻塞)因某事件或睡眠而被暂时性地挂起Dead:正常强行中断退出运行状态线程状态Java对多线程的支持提供对多线程的支持Thread类start(),stop(),run()Runnable接口实现多线程的两种编程方法继承Thread类实现Runnable接口第一种方法以多线程方式启动执行的类必须继承javalangThread类实现该类的run()方法然后控制线程的执行第二种方法如果只要一段代码在单独线程中运行则可以实现javalangRunnable接口实现run()方法然后通过构造Thread类对象实现线程的建立和运行控制。Thread类Thread类综合了Java程序中一个线程需要拥有的属性和方法当生成一个Thread类的对象后一个新的线程诞生了。每个线程都是通过目标对象的方法run()来完成其操作的。方法run()称为线程体(线程方法)。提供线程体的目标对象是在初始化一个线程时指明的。任何实现了Runnable接口(实现run()方法)的类实例都可以作为线程的目标对象。方法之一:继承Thread类Thread类的重要方法:run()定义线程的具体操作系统调度此线程时自动执行初始时无具体操作内容如何编程呢?-继承Thread类定义run()方法生成与运行线程–方法Thread例publicclassTestThread{publicstaticvoidmain(Stringargs){TreadthreadTreadthreadthread=newTread()创建线程thread=newTread()创建线程threadstart()启动线程threadstart()启动线程for(inti=i<=i){Systemoutprintln("主线程运行")}}}classTreadextendsThread{publicvoidrun(){for(inti=i<=i){Systemoutprintln("线程运行")}}}classTreadextendsThread{publicvoidrun(){for(inti=i<=i){Systemoutprintln("线程运行")}}}JVM首先将CPU资源给主线程。在主线程创建了两个线程并启动了这两个线程。所以在系统中总共有个线程在运行:主线程线程线程这个线程轮流使用CPU资源每个线程都有机会获得CPU的使用权。主线程运行的main方法返回JVM不再将CPU资源切换给主线程但是其他两个线程还没有结束Java程序没有结束。Thread类javalang包构造函数Thread()Thread(Stringthreadname)指定线程实例名voidstart():由Newborn到Runnable启动线程Thread类的有关方法run():线程在被调度时执行的操作staticvoidsleep(指定时间毫秒):令当前活动线程在指定时间段内放弃对CPU控制,使其他线程有机会被执行,时间到后重新需要排队产生异常InterruptedExceptionsuspend():挂起线程处于阻塞状态Thread类的有关方法(续)resume():恢复suspend挂起的线程重新进入就绪队列排队应用:可控制某线程的暂停与继续staticvoidyield():对正在执行的线程若就绪队列中有与当前线程同优先级的排队线程,则当前线程让出CPU控制权,移到排队的同优先级线程队尾若队列中没有同优先级的线程忽略此方法Thread类的有关方法(续)stop():强制线程生命期结束booleanisAlive():返回boolean,表明是否线程还存在interrupt():经常用来“吵醒”休眠的线程。当一些线程调用sleep方法处于休眠状态时一个占有CPU资源的线程可以让休眠的线程调用interrupt方法“吵醒”自己方法之二:RunnableRunnable接口自定义类实现Runnable接口使用Thread类的另一构造函数:Thread(Runnable,String)用实现了Runnable接口的类的对象中所定义的run()方法,来覆盖新创建的线程对象的run()方法使用start()启动线程生成与运行线程–方法RunnableclassMyRunimplementsRunnable{publicvoidrun(){线程体…}}MyRunmr=newMyRun()Threadt=newThread(mr)tstart()Thread实例用于线程控制适合于:定义run()方法的类必须是其他类或其他类的子类。sleep()方法staticvoidsleep(指定时间毫秒):令当前活动线程在指定时间段内放弃对CPU控制,使其他线程有机会被执行,时间到后重排队产生例外InterruptedException用try块调用sleep()用catch块处理例外publicclassTestThreadextendsThread{继承Thread类intthreadNumberpublicTestThread(intnum)线程类构造函数{threadNumber=num}publicvoidrun()线程体{Systemoutprintln("Thread"threadNumber"isrunning")try{Threadsleep()休眠ms}catch(InterruptedExceptionie){}Systemoutprintln(threadNumber"isfinished")}publicstaticvoidmain(Stringargs){Systemoutprintln("Creatingthread")Threadt=newTestThread()创建线程实例Systemoutprintln("Creatingthread")Threadt=newTestThread()tstart()启动线程tstart()}}CreatingthreadCreatingthreadThreadisrunningThreadisrunningisfinishedisfinishedinterrupt()介绍经常用来“吵醒”休眠的线程。当一些线程调用sleep方法处于休眠状态时一个占有CPU资源的线程可以让休眠的线程调用interrupt方法“吵醒”自己publicclassTestThreadextendsThread{publicvoidrun(){Systemoutprintln("IfeelsleepyWakemeineighthoursSleepbegin")try{Threadsleep()Systemoutprintln("SleependThatwasanicenap")}catch(InterruptedExceptionie){Systemerrprintln("Justfivemoreminutes")}}publicstaticvoidmain(Stringargs)throwsjavaioIOException{Threadsleepy=newTestThread()sleepystart()Systemoutprintln("Pressentertointerruptthethread")Systeminread()接收敲键sleepyinterrupt()打断线程休眠}}守护线程当程序中的所有用户线程都结束时立即结束的线程叫守护线程。守护线程用户线程:线程默认都是非守护线程也叫用户线程。用户线程需要执行完run方法中所有的语句才能结束。守护线程当程序中的所有用户线程都结束时即使守护线程的run方法中还有需要执行的语句守护线程也立即结束。守护线程voidsetDaemon(booleanon)一个线程调用setDaemon(booleanon)方法可以将自己设置成一个守护(Daemon)线程。线程必须在运行之前设置自己是否是守护线程。守护线程当程序中的所有用户线程都结束时即使守护线程的run方法中还有需要执行的语句守护线程也立即结束。因为守护线程会随时结束所以守护线程所做的工作应该是不很严格的工作可以随时结束而不影响运行结果的工作。守护线程在Java线程应用开发中经常使用。classMusicThreadextendsThread{publicvoidrun(){while(true){Systemoutprintln("音乐播放中")try{sleep()}catch(InterruptedExceptione){eprintStackTrace()}}}}publicclassInstallThreadextendsThread{publicvoidrun(){Systemoutprintln("安装开始")for(inti=i<=i=){Systemoutprintln("已安装"i"。")try{sleep()}catch(InterruptedExceptione){eprintStackTrace()}}Systemoutprintln("安装结束。")}publicstaticvoidmain(Stringargs){MusicThreadmusic=newMusicThread()musicsetDaemon(true)musicstart()InstallThreadinstall=newInstallThread()installstart()}}publicclassInstallThreadextendsThread{publicvoidrun(){Systemoutprintln("安装开始")for(inti=i<=i=){Systemoutprintln("已安装"i"。")try{sleep()}catch(InterruptedExceptione){eprintStackTrace()}}Systemoutprintln("安装结束。")}publicstaticvoidmain(Stringargs){MusicThreadmusic=newMusicThread()musicsetDaemon(true)musicstart()InstallThreadinstall=newInstallThread()installstart()}}如果音乐线程作为用户线程单独运行音乐线程永远不会停止。如果音乐线程设置成守护线程以后musicsetDaemon(true)用户线程执行完后音乐线程立即结束。线程同步当一个线程操作共享数据操作代码时其他想操作共享数据操作的代码就一直处于等待状态。在具有独占性权限的代码操作完成后会允许另外一个线程操作共享数据操作代码其他的线程继续等待。这称为线程同步。线程同步会计和职工的例子会计要给职工账户存入奖金万原来职工账户上余额万那么存入奖金后这个职工账户上的余额应该是万。后来这个职工想取款万。那么职工取款后他的账户余额应该是万。存款和取款是两个线程。存款和取款都用到同一个变量:账户余额。会计存款(万){读余额()返回余额=余额万}职工取款(万){读余额()返回余额=余额万}账户余额这个变量能在存款和取款这两个线程能同时进行修改吗?会计存款(万)职工取款(万)存款读余额()存款返回余额=余额万取款读余额()取款返回余额=余额万余额是万职工取款(万)会计存款(万)取款读余额()取款返回余额=余额万存款读余额()存款返回余额=余额万余额是万会计存款读余额()会计读出余额万职工取款读余额()职工读出余额万会计存款返回余额=余额万会计存款返回余额=余额万万=万职工取款返回余额=余额万职工取款返回余额=余额万万=万(!!!发生错误!!)最后余额是万。在多个线程共享同一个对象并且一个或者多个线程会对这个线程进行修改操作时如果不能正确的处理该共享对象会导致不确定的结果。比如一个线程在更新该对象的同时另外一个线程也试图对该对象进行更新则该对象会发生二次更新。如果在线程体中对一些访问共享数据或者不能打断顺序执行完整性的代码进行同步互斥控制就可以使各个线程以固定秩序访问共享数据从而避免这些问题。这种考虑了多线程竞争资源访问冲突的代码或程序称为线程安全的。当一个线程进入共享数据操作代码时其他想进入共享数据操作的代码就一直处于等待状态。在具有独占性权限的代码操作完成后会允许另外一个线程进入共享数据操作代码其他的线程继续等待。这称为线程同步。线程同步用synchronized关键字前缀给针对共享资源的操作加锁同步方法、同步块synchronizedvoidpush()synchronizedintpop()synchronized基本说法线程同步问题   线程同步是指几个线程都需要调用一个同步方法(使用关键字synchronized修饰的方法).同步机制 当一个线程A使用一个synchronized修饰的方法时其他线程想使用这个方法时就必须等待直到线程A使用完该方法(除非线程A使用wait主动让出CUP资源).synchronized关键首先要理解synchronized到底锁住了谁?()当一个线程访问一个对象的synchronized代码块时别的线程仍可以访问该对象的非synchronized代码块()当一个线程访问一个对象的synchronized代码块时任何其他线程都不可以再访问该对象的synchronized代码块例如:存款的方法publicsynchronizedintsaving(n){returnbalancen}死锁由多线程带来的性能改善是以可靠性为代价的主要是因为这样有可能产生线程死锁。我们来想像这样一种情形:在人行道上两个人迎面相遇为了给对方让道两人同时向一侧迈出一步双方无法通过又同时向另一侧迈出一步这样还是无法通过。双方都以同样的迈步方式堵住了对方的去路。假设这种情况一直持续下去双方都没有办法通过。操作系统中的著名的生产者和消费者问题线程间需协调与通讯:线程间协调与通讯生产者做面包消费者吃面包线程间协调与通讯面包没做出来消费者能吃到面包吗?面包已经做出来消费者没吃生产者还需要再做面包吗?线程间协调与通讯面包没做出来消费者想吃面包怎么办?面包已经做出来消费者没吃生产者想做下一个面包怎么办?线程间协调与通讯面包没做出来消费者想吃面包怎么办?消费者等待(等待生产者把面包做出来)面包已经做出来做的太多(比如大于个)消费者没吃生产者想做下一个面包怎么办?生产者等待(等待消费者把面包吃掉)线程间协调与通讯创建用户的线程子类Producer:产生数据(存数据)Consumer:消费数据(取数据)CubbyHole类共享数据区同步方法packagechclassBread{privateintsum=共享数据publicsynchronizedintget(intnum){while(sum<){try{Systemoutprintln("库有面包不足等待生产该消费者线程释放对面包房资源的独占进入等待状态(notify唤醒)")wait()}catch(InterruptedExceptione){eprintStackTrace()}}notify()intgetsif(num>sum){gets=sumsum=}else{sum=numgets=num}returngets}publicsynchronizedintput(intnum){while(sum>){try{wait()}catch(InterruptedExceptione){eprintStackTrace()}}sum=num***随机唤醒一个正在wait(该对象同步代码块)的线程*这里wait的只有只有消费者线程但注意消费者线程虽然醒了但现在还不能立即消费,*要等到生产者线程释放该对象的同步锁后(即执行完下面的代码离开同步块后)**notify()returnsum}}classProducerextendsThread{privateBreadbreadprivateintnumpublicProducer(Breadb,intn){bread=bnum=n}publicvoidrun()生产者一共生产{for(inti=i<=i){intputs=breadput(i)Systemoutprintln("Producer#"thisnum"put#"i"sum="puts)try{sleep()}catch(InterruptedExceptione){eprintStackTrace()}}}}classConsumerextendsThread{privateBreadbreadprivateintnumpublicConsumer(Breadb,intn){bread=bnum=n}publicvoidrun(){for(inti=i<=i){intgets=breadget(i)Systemoutprintln("Consumer#"thisnum"get#"i"gets:"gets)}}}publicclassProducerConsumerTest{publicstaticvoidmain(Stringargs){Breadbread=newBread()Consumercon=newConsumer(bread,)Producerpro=newProducer(bread,)constart()prostart()Systemoutprintln("主线程结束")}}线程的死锁线程锁住了对象A的监视器等待对象B的监视器线程锁住了对象B的监视器等待对象A的监视器就造成了死锁。如果你的持有一个锁并试图获取另一个锁时,就有死锁的危险synchronized关键首先要理解synchronized到底锁住了谁?()当一个线程访问一个对象的synchronized代码块时别的线程仍可以访问该对象的非synchronized代码块()当一个线程访问一个对象的synchronized代码块时任何其他线程都不可以再访问该对象的synchronized代码块wait、notify、notifyAll每一个对象除了有一个锁之外还有一个等待队列(waitset)当一个对象刚创建的时候它的等待队列是空的。我们应该在当前线程锁住对象的锁后去调用该对象的wait方法释放了当前线程对该对象的锁以使得别的线程有机会获得该对象的锁。当调用对象的notify方法时将从该对象的等待队列中删除一个任意选择的线程这个线程将再次成为可运行的线程。当调用对象的notifyAll方法时将从该对象的等待队列中删除所有等待的线程这些线程将成为可运行的线程。wait和notify主要用于producerconsumer这种关系中。一个线程wait后需要其他线程来唤醒它(执行notify)publicfinalvoidwait()方法在当前线程中调用方法:对象名wait()使当前线程进入等待(某对象)状态直到另一线程对该对象发出notify(或notifyAll)为止。特别注意的是它会释放对该对象的锁使得别的线程可以访问。调用方法的必要条件:当前线程必须具有对该对象的监控权(加锁)当前线程将释放对象监控权然后进入等待队列(wait队列)。在当前线程被notify后要重新获得监控权然后从断点处继续代码的执行。publicfinalvoidnotify()方法在当前线程中调用方法:对象名notify()功能:唤醒等待该对象监控权的一个线程。调用方法的必要条件:当前线程必须具有对该对象的监控权(加锁)notifyAll()唤醒wait队列中的所有线程并把它门移入锁申请队列。线程状态简述程序、进程和线程之间的关系。什么是多线程程序?线程有哪个基本的状态?它们之间如何转化?简述线程的生命周期。Runnable接口中包括哪些抽象方法?Thread类有哪些主要域和方法?如何在Java程序中实现多线程?试简述使用Thread子类和实现Runnable接口两种方法的异同。

用户评价(0)

关闭

新课改视野下建构高中语文教学实验成果报告(32KB)

抱歉,积分不足下载失败,请稍后再试!

提示

试读已结束,如需要继续阅读或者下载,敬请购买!

评分:

/84

VIP

在线
客服

免费
邮箱

爱问共享资料服务号

扫描关注领取更多福利