资源预览内容
第1页 / 共54页
第2页 / 共54页
第3页 / 共54页
第4页 / 共54页
第5页 / 共54页
第6页 / 共54页
第7页 / 共54页
第8页 / 共54页
第9页 / 共54页
第10页 / 共54页
亲,该文档总共54页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述
第八章 多线程机制 8.1 Java多线程机制 (概念掌握,理解性内容) 8.2 多线程的实现方法(重点及难点) 8.3 多线程状态及调度(重点) 8.4 线程同步 8.5 线程通信n18.1 Java多线程机制 8.1.1 线程的基本概念 线程的概念:线程就是应用程序中的一个可 执行线索,多线程就是同一个应用程序中有 多个可执行线索,它们可以并发执行。 为什么要有多线程? 线程与进程的区别: 可否独立运行? 内存空间?n2案例用程序来模拟铁路售票系统,实现通过四个售票点发售某日某次列车的100张车票,要求这四个售票点同时售票。这就需要一个程序能够同时执行4个任务。n3所需要的知识点 什么是多线程 如何实现多线程 如何调度和控制多线程n4多线程概述大多数程序设计时,习惯上考虑该程序如何从头至尾顺序执行各项任务的设计方法 ,即一个程序只有一条执行路线。但现实世 界中的很多过程都是同时发生的,对应这种 情况,可编写有多条执行路径的程序,使得程序能够同时执行多个任务。 n5线程的基本概念 线程是程序中的一条执行路径。多线程是指程序中包含多条执行路径。 在一个程序中可以同时运行多个不同的线程来执行不同的任务。n6多线程基本概念n7多线程的例子 浏览器程序 聊天程序n8v 进程:简单地说,在多任务系统中,每个独立执行的 程序称为进程,也就是“正在运行的程序”。v 线程:进程中程序代码的一个执行序列。线程并不是 程序,它自己本身并不能运行,必须在程序中运行。在 一个程序中可以实现多个线程,这些线程同时运行,完 成不同的功能。进程与线程n9线程与进程的区别进程和线程相比,主要有以下区别: 两者的粒度不同,是两个不同层次上的概念。 进程是由操作系统来管理的,而线程则是在一 个程序(进程)内。 不同进程的代码、内部数据和状态都是完全独 立的,而一个程序内的多线程是共享同一块内 存空间和同一组系统资源,有可能互相影响。 线程本身的数据通常只有寄存器数据,以及一 个程序执行时使用的堆栈,所以线程的切换比 进程切换的负担要小。n10分时操作系统 可以同一时间执行多个程序的操作系统 CPU只是将时间切割为时间片,然后将时间片 分配给这些程序,获得时间片的程序开始执行 ,不等执行完毕,下个程序又获得时间片开始 执行,给人的感觉就像是多个程序在同时执行 一样。 Java的多线程就是在操作系统每次分时给Java 程序一个时间片的CPU时间内,在若干独立的 可控制的线程之间切换。n11多线程编程的优点 减轻编写交互频繁、涉及面多的程 序的困难 程序的吞吐量会得到改善 由多个处理器的系统,可以并发运行 不同的线程。(否则,任何时刻只有 一个线程在运行)n12多线程机制 一个建立线程的例子:public class SimpleRunnable implements Runable private String message; public static void main(String args) SimpleRunnable r1=new SimpleRunnable(“Hello“); Thread t1=new Thread(r1); t1.start(); public SimpleRunnable(String message) this.message = message; public void run() for(;) System.out.println(message); 线程开始执行时,它在public void run()方法中执行。 该方法是定义的线程执行起点,像应用程序从main()开始一样。首先main()方法构造SimpleRunnable类的实例。实例有自己的一个String数据,初始化为“Hello“。由实例r1传入 Thread类构造器,这是线程运行时处理的数据。 执行的代码是实例方法run()。n138.2 多线程的实现方法 重点与要点:两种实现方法 创建Thread子类 生成一个类,声明实现Runnable接口n14创建Thread类的子类 用这种方法生成新线程,可以按以下步骤进行:1.生成Thread类的子类。class MyThread extends Thread2.在子类中覆盖run()方法。public void run()3.生成子类的对象,并且调用start()方法启动新线程。MyThread thread = new MyThread();thread.start();start()方法将调用run()方法执行线程。n15实现Thread子类方法的多线程示例 class FirstThread extends Thread public void run() trySystem.out.println(“First thread starts running.“);for(int i=0; i Thread类的子类。实现runnable接口相对于继承Thread类来说,具有以下优点 :v可以避免由于Java单继承特性带来的局限。v有利于程序的健壮性,代码能够被多个线程共享,代码 与数据是独立的。 n328.3多线程状态及调度 1线程的状态 具有四种状态: 新生态:已分配内在,未高度 可执行态:start( ) 阻塞态 停止态:stop( ) n33线程状态四种状态的相关概念生命周期如下:1新建:当一个Thread类或其子类的对象被创建后,进 入这个状态。这时,线程对象已被分配内存空间,其私有数 据已被初始化,但该线程还未被调度,可用 start()方法调度,或用stop()方法中止。新生线程一旦被调度,就将切换到可执行状 态。n34线程状态2可运行:处于可执行环境中,随时可以被调度而执行。它 可细分为两个子状态:运行状态,已获得CPU,正在执行;就绪状态,只等待处理器资源。这两个子状态的过渡由执行调度器来控制。3阻塞:由某种原因引起线程暂停执行的状态。n35线程状态4死亡:线程执行完毕或另一线程调用stop()方法使其停止时,进入这种停止状态。它表示线程已退出可运行状态,并且不再 进入可运行状态。 n368.3.2 线程优先级及调度 问题:线程为什么需要调度?为什么引入优先级? 应用程序中的多个线程能够并发执行,但从系统的内部来 看,所有线程仍然是串行的一个一个地执行,那么如何来 决定哪一个线程先执行,哪一个线程后执行呢? Java引入了优先级的概念,优先级就是线程获得CPU而执 行的优先程度,优先级越高,获得CPU的权力越大,执行 的机会越多,执行的时间也越长。 n37线程优先级 Java把优先级划分为10级,用1至10的整数表示,数 值越大,优先级越高。 在Thread类中定义了三个优先级常量: MIN_PRIORITY, MAX_PRIORITY和NORM_PRIORITY, 其值分别为1, 10, 5。 在为线程分配优先级时,其值应该在1至10之间, 否则将出错。 如果应用程序没有为线程分配优先级,则Java系统 为其赋值为NORM_PRIORITY。 n38线程调度原则 调度就是分配CPU资源,确定线程的执行顺序。 Java采用抢占式调度方式,即高优先级线程具有剥 夺低优先级线程执行的权力。 如果一个低优先线程正在执行,这时出现一个高优 先级线程,那么低优先级线程就只能停止执行,放 弃CPU,推回到等待队列中,等待下一轮执行,而 让高优先级线程立即执行。 如果线程具有相同的优先级,则按“先来先服务“的 原则调度。 n39线程调度原则 问题:如果高优先级抢占了低优先级的线程后,一 直占据CPU,低优先级的线程如何获得控制权? 有两个方法可以改变这种现象:一是调用sleep()方法,暂时进入睡眠状态,从而让出 CPU,使有相同优先级线程和低优先级线程有执行的机 会。二是调用yield()而放弃CPU,这时和它有相同优先级的线 程就有执行的机会。 n408.3.3 线程的控制必须了解Java程序的线程结构: 每个Java程序都有一个缺省的主线程:Application,主线程是main方法执行的线索;Applet,主线程指挥浏览器加载并执行Java小程序。 要想实现多线程,必须在主线程中创建新的线程对 象。n41线程的状态转换图阻塞死亡可运行suspend() sleep() wait() I/O blockingresume() sleep time_out notify() I/O finished新建new语句start()Stop()Stop()Stop()n42线程控制方法Thread类定义了许多控制线程执行的方法。 程序中经常使用下面的方法,对线程进行控制: start():用于调用run()方法使线程开始执行。stop(): 立即停止线程执行,其内部状态清零 ,放弃占用资源。suspend():暂停线程执行。线程的所有状态和 资源保持不变,以后可以通过另一线程调用 resume()方法来重新启动这个线程。 n43线程控制方法resume():恢复暂停的线程,安排暂停线程执行。 sleep(): 调整Java执行时间,所需参数是指定线程的睡眠时间,以毫秒为单位。join():调用线程等待本线程执行结束。yield():暂停调度线程并将其放在等待队列末尾,等待下一轮执行,使同优先级的 其它线程有机会 执行 。 n44线程控制方法 isAlive(): 线程处于“新建”状态时,线程调用方法返回false。 当一个线程调用start()方法,并占有CPU资源后,该 线程的run方法就开始运行,在线程的run方法结束之 前,即没有进入死亡状态之前,线程调用isAlive()方法 返回true。 当线程进入“死亡”状态后(实体内存被释放),线程仍可以调用方法isAlive(),这时返回的值是false。n458.4 线程同步为什么需要线程同步? 多线程提高了程序的并发度,但是有时候是不安全的或者不合 逻辑的。则需要多线程同步。 线程同步是多线程编程的一个相当重要的技术。 多线程同步控制机制:保证同一时刻只有一个线程访问数据资 源。 同步锁:Java用锁标志(lock flag)的手段,对被访问的数据 进行同步限制,从而实现对数据的保护。 把所有被保护资源都加上锁标志,线程必须取得锁标志才能访 问被保护的资源。n46线程同步 在Java中,使用修饰符synchronized来为被保护资源 加锁。 synchronized只能用来说明方法和代码段,不能用它 来说明类和成员变量。 用synchronized修饰的方法和代码段称为方法同步和 代码段同步,它意味着同一时刻该方法或代码段只能 被一个线程执行,其它想执行该方法或代码段的线程 必须等待。 方法同步仅在该方法前加上synchronized修饰符即 可。n47线程同步 同步操作是以牺牲CPU资源为代价的。 正确使用同步可以减少线程间的相互干扰,提高程序的稳定性和可靠性。 Java程序中多个线程可以通过消息来实现互动联系的,通常可以用notify()或notifyAll()方法唤醒其它一个或所有线程。 使用wait()方法来使该线程处于阻塞状态,等待其它的线程用notify()唤醒。n488.5 线程通信 wait方法和notify方法是Java同步机制中重要的组成部分。 结合与synchronized关键字使用,可以建立很多优秀的同步模型。 同步分为类级别和对象级别,分别对应着类锁和对象锁。 如果static的方法被synchronized关键字修饰,则在这个方法被执行前必须获得类锁。对象锁类似。n49wait和notify的应用示例import ja
收藏 下载该资源
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号