《Java程序设计与应用》-张仕斌-电子教案 第9章

上传人:E**** 文档编号:89401285 上传时间:2019-05-24 格式:PPT 页数:30 大小:496.50KB
返回 下载 相关 举报
《Java程序设计与应用》-张仕斌-电子教案 第9章_第1页
第1页 / 共30页
《Java程序设计与应用》-张仕斌-电子教案 第9章_第2页
第2页 / 共30页
《Java程序设计与应用》-张仕斌-电子教案 第9章_第3页
第3页 / 共30页
《Java程序设计与应用》-张仕斌-电子教案 第9章_第4页
第4页 / 共30页
《Java程序设计与应用》-张仕斌-电子教案 第9章_第5页
第5页 / 共30页
点击查看更多>>
资源描述

《《Java程序设计与应用》-张仕斌-电子教案 第9章》由会员分享,可在线阅读,更多相关《《Java程序设计与应用》-张仕斌-电子教案 第9章(30页珍藏版)》请在金锄头文库上搜索。

1、第九章 多线程,2019年5月24日星期五,2,学习目的: 掌握多线程的基础知识 掌握线程的生命周期 了解线程的优先级 了解用线程制作动画的方法 学习重点: 多线程的基础知识 线程的生命周期,2019年5月24日星期五,3,第九章 多线程,本章提要: 多线程编程基础 线程的基本概念、线程模型、Thread类、Runnable接口、线程间的数据共享、多线程的同步控制与通信和守护线程 2.线程的生命周期 线程的几种基本状态、死锁问题和控制线程的生命 3.线程的优先级 4.用于制作动画的线程 动画程序框架、帧的画法、避免闪动与使用图片,9.1 多线程编程基础,Java与现在流行的通用目的编程语言相比

2、有个独特之处,它使用程序员可以使用的并发原语。程序员指定在程序中包含要执行的多个线程,每个线程设计成程序的一部分,并且能与其他线程并发执行,这种功能称为多线程。,2019年5月24日星期五,5,应用程序 存储在计算机系统的存储空间中的一段静态的代码序列 进程 处在可执行状态中的应用程序称为进程。从用户角度来看,进程是应用程序的一个执行过程。从操作系统核心角度来看,进程代表的是操作系统分配的内存、CPU时间片等资源的基本单位,是为正在运行的程序提供的运行环境。 线程 Java语言中定义的线程(Thread)包括一个内存入口点地址、一个出口点地址以及能够顺序执行的代码序列。但线程不能够单独执行,它

3、必须运行在处于活动状态的应用程序进程中,因此可以定义线程是程序内部的具有并发性的顺序代码流。,9.1.1线程的基本概念,2019年5月24日星期五,6,多线程模型的同步方式。 所有的对象都有充当互斥锁的内置侦听器。在给定的时刻,任何侦听器只能由一个线程拥有。通过使用synchronized关键字对方法进行修饰,可以启用锁定特性。在调用同步方法时,该对象就被锁定,而试图访问该对象的其他线程就只能等待。 Java对同步的支持可以通过wait()、notify()和notifyAll()方法来实现。 线程类(Thread) 线程类封装了所有需要的线程操作控制。必须很清楚地区分线程对象和运行线程,线程

4、对象可以看作是运行线程的控制面板。线程类是控制线程行为的惟一手段。一个Java程序启动后,就已经有一个线程在运行。可以通过调用Thread.currentThread()方法来查看当前运行的是哪一个线程 例9-1,9.1.2Java的线程模型,2019年5月24日星期五,7,Thread类的构造函数: Public Thread(String threadName):用于构造一个名为threadName的Thread对象 public Thread():则用于构造名为“Thread-”加上一个数字的线程,如“Thread-1”、“Thread-2”等。 Run方法可以在Thread的子类中覆盖

5、或在Runnable对象中覆盖。 程序通过调用线程的start方法执行线程,而start则调用Run方法。当start方法启动线程后,start便立即返回到其调用者。调用者与这一线程并发执行。如果start方法试图启动一个已经执行的线程,则会抛出IllegalThreadStateException异常。,9.1.3Thread类,2019年5月24日星期五,8,public static native void sleep(long millis) throws InterruptedException:该方法中的millis参数指出当前执行的线程应休眠多长时间(单位为ms)。线程休眠时不会

6、竞争处理器,因此处理器便可以运行其他线程。 Interrupt方法用于中断一个线程。如果线程已经被中断,该方法便返回true,否则返回false。程序可以调用isInterrupted方法确定该线程是否被中断。 setName方法用于设置线程的名称; getName方法用于返回线程的名称; toString方法返回一个包含线程名称、线程优先级和线程所属线程组的字符串; currentThread方法返回一个对当前线程的引用。,9.1.3Thread类,2019年5月24日星期五,9,创建新的执行线程的方法: 创建一个Thread类的子类,该类重载run方法即可 实现 Runnable 接口,并

7、实现run方法。 Runnable的使用 使用Runnable对象的程序会创建一个Thread对象,并把Runnable对象与该Thread对象关联。Thread类提供了两个构造函数实现和runnable对象相关联 public Thread(Runnable runnableObject):将runnableObject对象的run方法注册为线程开始执行时调用的方法。 public Thread(Runnable runnableObject,String threadName):以threadName为名称构造一个线程,并将参数runnableObject对象的run方法注册为线程开始执行

8、时调用的方法。 例9-2,9.1.4 Runnable接口,2019年5月24日星期五,10,冲突的产生 如果应用程序是多线程的应用程序,一个Java程序的多线程之间可以共享数据,就存在两个或更多个线程同时使用相同且有限的资源的可能性。 冲突的避免 在Java内部内置了一种机制,可防止资源的冲突。当定义一个类的时候,常常会将类的某些属性声明为private,并且由函数来访问其内容,同样,可以将某个函数声明为synchronized(同步化)来防止冲突的发生。这样,每个对象就都含有一个机锁,当调用任何synchronized函数时,对象便被锁定,该对象的所有synchronized函数都无法再被

9、调用,直到第一个函数执行完毕并解除锁定为止。,9.1.5 线程间的数据共享,2019年5月24日星期五,11,多线程同步控制机制 当第一个线程读取完数据时,第二个线程才能处理该数据。 同步控制的实现 在Java的关键字中,有一个“synchronized”的关键字,它就可以实现同步,实现对共享数据协调操作。在声明一个类时,用synchonized修饰的方法为同步方法。Java中有一个同步模型-监视器,负责管理线程对象中的同步方法的访问,它的原理是:赋予该对象惟一的一把“钥匙”,当多个线程进入对象,只有取得该对象钥匙的线程才可以访问同步方法,其他线程都必须等待。直到该线程用wait()方法放弃这

10、把钥匙,其他等待的线程抢占该钥匙,抢占到钥匙的线程才可得以执行,而没有取得钥匙的线程仍被阻塞,必须继续等待。 例9-3,9.1.6 多线程的同步控制,2019年5月24日星期五,12,用于在不同线程(threads)间进行通信采用是的管道流。管道流是一种特殊的流。一个线程发送数据到输出管道,另一个线程从输入管道中读数据。 管道的创建与使用 Pipedinputstream代表了数据在管道中的输出端,也就是线程向管道读数据的一端;pipeoutputstream代表了数据在管道中的输入端,也就是线程向管道写数据的一端,这两个类一起使用可以提供数据的管道流。要创建一个管道流,必须先创建一个pipe

11、outstream对象,然后,创建pipeinputstream对象,如下: pipeout= new pipedyoutstream(); pipein= new pipedputsteam(pipepout); 实现线程间的通信 例9-4 ythread zthread,9.1.7 线程之间的的通信,2019年5月24日星期五,13,守护线程是为其他线程的运行提供服务的线程。一般在后台运行。垃圾回收器就是一个守护线程。 非守护线程一般是用户线程或用于处理GUI事件的事件调度线程。 守护线程的定义:setDaemon(true); 如果参数为false,则该线程为非守护线程。一个程序可以包括

12、守护线程和非守护线程。当程序中只有守护线程时,程序便结束运行。如果要使一个线程为守护线程,必须在调用其start方法之前进行以上设置,否则会产生IllegalThreadStateException异常。如果线程是守护线程,则isDaemon方法返回true,否则返回false。,9.1.8 守护线程,9.2 线程的生命周期,任何一个线程都有自己的生命周期,其中包括创建、可运行、运行中、等待、休眠、阻塞和死亡7种状态。在线程的生命周期中,任何一个线程都是处于这七种状态中的某一种状态,其状态并随程序的执行在不断的变化。,2019年5月24日星期五,15,9.2.1 线程的几种基本状态,2019年

13、5月24日星期五,16,9.2.1 线程的几种基本状态,创建状态:使用new运算符创建一个线程后,该线程仅仅是一个空对象,系统没有分配资源,称该线程处于创建状态。在调用线程的start方法之前,该线程将一直处于创建状态(new thread)。 可运行状态:使用start()方法启动一个线程后,系统为该线程分配了除CPU外的所需资源,使该线程处于可运行状态(Runnable)。 运行中状态:Java运行系统通过调度选中一个可运行的线程,使其占有CPU并转为运行中状态(Running)。此时,处于可运行状态的最高优先级线程便进入了运行状态,系统真正执行线程的run()方法,即线程开始执行。 死亡

14、状态:如果线程的run方法结束或由于其他原因终止,则该线程便进入了死亡状态;系统最终会抛出死亡的线程。 阻塞状态:如果处于运行状态的线程发出输入/输出请求,它便进入阻塞状态。当其等待的I/O操作结束时,阻塞的线程便回到可运行状态。对于阻塞的线程来说,即使处理器空闲,它也不能使用。 休眠状态:当程序调用一个正在运行的线程的sleep方法时,该线程便会进入休眠状态。进入休眠的线程在其预先设置的休眠时间到了以后,便进入可运行状态。对于休眠的线程来说,即使处理器空闲,它也不能用。如果程序调用一个休眠线程的interrupt方法,该线程会退出休眠状态,并进入可运行状态准备执行。 等待状态:当处于运行状态

15、的线程调用wait方法时,线程便进入等待状态。它将按次序在等待队列中,队列中的线程均是由于某个对象调用了wait方法才进入等待状态的。当与某个对象相关的另一个线程调用了notifyAll方法后,等待该对象的所有线程都回到可运行状态。,2019年5月24日星期五,17,9.2.2 死锁问题,死锁的定义:,线程A可能会陷入对线程B的等待,而线程B同样陷入对线程C的等待,依此类推,整个等待最后又回到了线程A,于是各线程便陷入一个彼此等待的轮回中,任何线程都动弹不得,这种现象便称为死锁。 导致死锁的情况: 相互排斥:一个线程永远占有一共享资源,例如,独占该资源。 循环等待:线程A等待线程B,而线程B又

16、在等待线程C,而线程C又在等待线程A。 部分分配:资源被部分分配。例如,线程A和B都需要访问一个文件,并且都要用到打印机,线程A获得了文件资源,线程B获得了打印机资源,但是两个线程不能获得全部的资源。 缺少优先权:一个线程访问了某个资源,但是一直不释放该资源,即使该线程处于阻塞状态。,2019年5月24日星期五,18,9.2.3 控制线程的生命,start( )方法:使该线程开始执行; Java 虚拟机调用线程 run 方法。 run( )方法:当编写Thread类的子类时,该方法必须进行覆写,把要在多个线程中并行处理的代码放到这个函数中。 sleep( )方法:Thread类的静态方法,可以被类名直接调用,作用是使线程睡眠一段时间,单位为毫秒;当调用sleep ()函数后,线程不会释放它的“锁标志”。 例9-5,2019年5月24日星期五,19,9.2.3 控制线程的生命,wait( )方法:通过wait()函数,可使本线程中断方法的执行,使本线程等待,暂时让出CPU的使用权,并允许其他线程使用这个同步方法。当调用wait()后,线程会释放掉它所占有的“锁标志”,从而使线程

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 高等教育 > 大学课件

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号