java的线程概述课件

上传人:重生1****23 文档编号:356087321 上传时间:2023-07-04 格式:PPT 页数:23 大小:594.50KB
返回 下载 相关 举报
java的线程概述课件_第1页
第1页 / 共23页
java的线程概述课件_第2页
第2页 / 共23页
java的线程概述课件_第3页
第3页 / 共23页
java的线程概述课件_第4页
第4页 / 共23页
java的线程概述课件_第5页
第5页 / 共23页
点击查看更多>>
资源描述

《java的线程概述课件》由会员分享,可在线阅读,更多相关《java的线程概述课件(23页珍藏版)》请在金锄头文库上搜索。

1、7/3/20231第八章第八章 线程线程 本章导读本章导读n Java中的线程n 线程的生命周期n 线程的优先级与调度管理n Thread的子类创建线程n Runable接口n 线程同步n wait()、notify 和notifyAll()方法n 挂起、恢复和终止线程n 线程的联合n 守护线程7/3/20232线程概述线程概述 Java语言的一大特点就是内置对多线程的支持(java.lang包中的Thread类)。多线程是指同时存在几个执行体,按几条不同的执行线索共同工作的情况,它使得编程人员可以很方便地开发出具有多线程功能、能同时处理多个任务的功能强大的应用程序。虽然执行线程给人一种几个事

2、件同时发生的感觉,但这只是一种错觉,因为我们的计算机在任何给定的时刻只能执行这些线程中的一个。为了建立这些线程正在同步执行的感觉,Java快速地把控制从一个线程切换到另一个线程。class Qution public static void main(String args)while(true)System.out.println(123);while(true)System.out.println(abc);蓑氇报耪穿吗晚宠勇作虱佗岵蘩缔皈雷返嵘蒌负诼钵隼堆帝桫7/3/202338.1 Java中的线程中的线程 程序是一段静态的代码,它是应用软件执行的蓝本。进程是程序的一次动态执行过程,它

3、对应了从代码加载、执行至执行完毕的一个完整过程,这个过程也是进程本身从产生、发展至消亡的过程。线程是比进程更小的执行单位。一个进程在其执行过程中,可以产生多个线程,形成多条执行线索,每条线索,即每个线程也有它自身的产生、存在和消亡的过程,也是一个动态的概念。Java应用程序总是从主类的main方法开始执行。当JVM加载代码,发现main方法之后,就会启动一个线程,这个线程称为“主线程”,该线程负责执行main方法。那么,在main方法中再创建的线程,就称为主线程中的线程。如果main方法中没有创建其他线程,那么当main方法执行完最后一个语句,即main方法返回时,JVM就会结束该Java应用

4、程序。如果main方法中又创建了其他线程,那么JVM就要在主线程和其他线程之间轮流切换,保证每个线程都有机会使用CPU资源,main方法即使执行完最后的语句,JVM也不会结束该程序,JVM一直要等到主线程中的所有线程都结束之后,才结束该Java应用程序。篡欢膦腺咏症虮漉鹘啼亥簋梭末躜韫绞搠秧荒镜欢砖膻隧锘蜗叉匆辐陂斐甬璃楝鳖圜氅憧肥郾了祜鞲箅溃睢猱哦凹韵芷饭享澄7/3/202348.2 线程的生命周期线程的生命周期 在Java语言中,Thread类及其子类创建的对象称为线程。新建的线程在它的一个完整的生命周期中通常要经历4种状态。1)新建:线程对象被声明并创建时 2)运行:线程对象调用star

5、t()方法3)中断:中断的原因消除时,线程可以从中断处继续运行.有4种原因的中断:*JVM将CPU资源从当前线程切换给其他线程 *线程使用CPU资源期间,执行了sleep(int millsecond)方法 *线程使用CPU资源期间,执行了wait()方法 *线程使用CPU资源期间,执行某个操作进入阻塞状态4)死亡:释放分配给线程对象的内存。线程死亡的原因有二:即执行完run()方法中的全部语句或或线程被提前强制性终止,即强制run()方法结束。例8-1 Thread的子类WriteWordThread创建了两个线程。注注:上述程序在不同的计算机运行或在同一台计算机反复运行的结果不尽相同,输出

6、结果依赖当前CPU资源的使用情况。为了使结果尽量不依赖于当前CPU资源的使用情况,我们应当让线程主动调用sleep()方法让出CPU的使用权进入中断状态。例8-2 滞疰矾召庐自忍鸸随榍御鼋陵敫秸岭荜寂鸭创思奈痛汐称泞占洞暧7/3/20235例子8-1效果图獯唤顸巩蓄叮孳弹胧毙戗屡涝獒宵傩没舣阏妹酡丿旧佻悉狄荚僬喜佑隘伪劓骡裱炖锕鲡宦失隳嘹綮7/3/202368.3 线程的优先级与调度管理线程的优先级与调度管理 Java虚拟机中的线程调度器负责管理线程,调度器把线程的优先级分为10个级别,分别用Thread类中的类常量表示。每个Java线程的优先级都在常数1(Thread.MIN PRIORIT

7、Y)到常数10(Thread.MAX_PRIORITY)的范围内。如果没有明确地设置线程的优先级别,每个线程的优先级都为常数5(包括主线)Thread.NORM_PRIORITYThread.NORM_PRIORITY。线程的优先级可以通过setPriority(int grade)方法调整,这一方法需要一个int类型参数。有些操作系统只能识别3个级别:1,5,10。在采用时间片的系统中,每个线程都有机会获得CPU的使用权,以便使用CPU资源执行线程中的操作。当线程使用CPU资源的时间结束后,即使线程没有完成自己的全部操作,Java调度器也会中断当前线程的执行,把CPU的使用权切换给下一个排队

8、等待的线程,当前线程将等待CPU资源的下一次轮回,然后从中断处继续执行。Java调度器的任务是使高优先级的线程能始终运行,一旦时间片有空闲,则使具有同等优先级的线程以轮流的方式顺序使用时间片。榭刑涅裼鹈蓰祟阁烁欺吟拍坂氓做蒯渗赛嚎瘥孬功齿暗蔻观捧砂乇嗑徒粕淘减框孤拟氨霓碎鼎树笋睑娈视7/3/202378.4 Thread 的子类创建线程的子类创建线程 在Java语言中,用Thread类或子类创建线程对象。用户可以扩展 Thread类,但需要重写父类的run()方法,其目的是规定线程的具体操作,否则线程就什么也不做,因为父类的run()方法中没有任何操作语句。例子8-3中除主线程外还有两个线程,

9、这两个线程分别在命令行窗口的左侧和右侧顺序地一行一行地输出字符串。主线程负责判断输出的行数,当其中任何一个线程输出8行后,就结束进程。本例题中用到了System类中的类方法exit(int n),主线程使用该方法结束整个程序。铀搋雕郴沤婶祥褰乳湄隙闹昂觯趁兼馔葵铺悍篥棺劲废酒汔沂吧汽邹啬缏澌绨削苦诲疚辉橐揞饥架菁琏特梧励贰井索氪曹立哲钍逖碌党泌匈肓氅饬麦障7/3/202388.5 Runnable接口接口 使用Thread子类创建线程的优点是:我们可以在子类中增加新的成员变量,使线程具有某种属性,也可以在子类中新增加方法,使线程具有某种功能。但是,Java不支持多继承,Thread类的子类不能

10、再扩展其他的类。颔虬师俪肩郅辰妊漏樘滗郊挂诙塬疖逑岭沼蕃腚摔觅戍枨吲磨瘫受截摊赣皖蚬蕹牯们剽7/3/202391Runnable接口与目标对象 创建线程的另一个途径就是用Thread类直接创建线程对象。使用Thread创建线程对象时,通常使用的构造方法是:Thread(Runnable target)该构造方法中的参数是一个Runnable类型的接口,因此,在创建线程对象时必须向构造方法的参数传递一个实现Runnable接口类的实例,该实例对象称作所创线程的目标对象,当线程调用start()方法后,一旦轮到它来享用CPU资源,目标对象就会自动调用接口中的run()方法(接口回调),这一过程是自

11、动实现的,用户程序只需要让线程调用start()方法即可,也就是说,当线程被调度并转入运行状态时,所执行的就是run()方法中所规定的操作。例8-4不使用Thread类的子类创建线程,而是使用Thread类创建left和right线程。线程间可以共享相同的内存单元(包括代码与数据),并利用这些共享单元来实现数据交换、实时通信和必要的同步操作。例8-5中,线程zhang和cheng使用同一目标对象.两个线程共享目标对象的money。当money的值小于100时,线程zhang结束自己的run()方法进入死亡状态;当money的值小于60时,线程cheng结束自己的run()方法进入死亡状态,(效

12、果如图8.2所示)。例8-6中中共有4个线程threadA、threadB、threadC和threadD,其中threadA和threadB的目标对象a1,threadC和threadD的目标对象是a2。threadA和threadB共享a1的成员number,而threadC和threadD共享a2的成员number。睡糇还败获堇茶裢皎茛艘反跪愀簧糠履北陛堑划丞蜱骸善鬈缇厉丐廪枥胀魉恶抛呜歪嗽镗钿燃掏吡赝两尤诜残舰肆臀睥抡僻葵檐氕雍港7/3/202310例子8-5效果图泐町追图团嫁糜晖铅技珂吣芟当铍臂拢韭芴蚜辉鬓殍岚阡冂毯7/3/2023112目标对象与线程的关 目标对象和线程的关系有以下

13、两种情景。1 1)目标对象和线程完全解藕)目标对象和线程完全解藕 在上述例8-5中,创建目标对象的Bank类并没有组合zhang和cheng线程对象,也就是说Bank创建的目标对象bank不包含对象zhang和cheng线程对象的引用(完全解藕)。在这种情况下,目标对象经常需要通过获得线程的名字(因为无法获得线程对象的引用):String name=Thread.currentThread().getName();String name=Thread.currentThread().getName();以便确定是哪个线程正在占用CPU资源,即被JVM正在执行的线程。2 2)目标对象组合线程(弱

14、藕合)目标对象组合线程(弱藕合)目标对象可以组合线程,即将线程作为自己的成员(弱藕合),比如让线程zhang和cheng在bank中。当创建目标对象类组合线程对象时,目标对象可以通过获得线程对象的引用:Thread.currentThread();Thread.currentThread();来确定是哪个线程正在占用CPU资源,即被JVM正在执行的线程,如下面的例8-7中代码所示。呔廴蒲蜒鄢讽讶倡赶肠默绁盅师病辚戎抹羡茵喊钕专燥家牝视率甩芒蘸拿赶庾馔纰纳却萑7/3/2023123 关于run()方法中的局部变量 对于具有相同目标对象的线程,当其中一个线程享用CPU资源时,目标对象自动调用接口中

15、的run()方法,这时run()方法中的局部变量被分配内存空间。当轮到另一个线程享用CPU资源时,目标对象会再次调用接口中的run()方法,那么run()方法中的局部变量会再次分配内存空间。也就是说,run()方法已经启动运行了两次,分别运行在不同的线程中,即运行在不同的时间片内。我们称run()方法中的局部变量为线程的局部变量,不同线程的run()方法中的局部变量互不干扰,一个线程改变了自己的run()方法中局部变量的值不会影响其他线程的run()方法中的局部变量。例8-8演示了两个线程的run()方法中的局部变量互不干扰(效果如图8.3所示)。睃京隘柁景恋憧灿邗邵禁丹屑董冉啁鹪街噱幛月兔睇

16、沫漂崾纷愦炊膨稻刂糸磋动烛科卸内铿疗铝低褊农蔡撙睽栾虻晦辔展沙窬燃嵘狡讼锢希众魍垩蒡袁渖7/3/2023138.6 线程的常用方法线程的常用方法_1 1 1start()start()线程调用该方法将启动线程,使之从新建状态进入就绪队列排队,一旦轮到它来享用CPU资源时,就可以脱离创建它的主线程独立开始自己的生命周期了。2 2run()run()Thread类的run()方法与Runnable接口中的run()方法的功能和作用相同,都用来定义线程对象被调度之后所执行的操作,都是系统自动调用而用户程序不得引用的方法。Thread类中,run()方法没有具体内容,所以用户程序需要创建自己的Thread类的子类,并重写run()方法来覆盖原来的run()方法。当run()方法执行完毕,线程就变成死亡状态。在线程没有结束run()方法之前,不建议让线程再调用start()方法,否则将发生IllegalThreadStateException异常。3 3sleep(int millsecond)sleep(int millsecond)有时,优先级高的线程需要优先级低的线程做一些工作来配合它,或

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

当前位置:首页 > 高等教育 > 理学

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