第16章多线程

上传人:桔**** 文档编号:570506407 上传时间:2024-08-04 格式:PPT 页数:69 大小:220.50KB
返回 下载 相关 举报
第16章多线程_第1页
第1页 / 共69页
第16章多线程_第2页
第2页 / 共69页
第16章多线程_第3页
第3页 / 共69页
第16章多线程_第4页
第4页 / 共69页
第16章多线程_第5页
第5页 / 共69页
点击查看更多>>
资源描述

《第16章多线程》由会员分享,可在线阅读,更多相关《第16章多线程(69页珍藏版)》请在金锄头文库上搜索。

1、第第16章章多线程多线程本章要点本章要点u了解多线程在了解多线程在Windows系统的执行模式系统的执行模式u掌握实现线程的两种方式掌握实现线程的两种方式u掌握线程的状态掌握线程的状态u掌握使线程进入各种状态的方法掌握使线程进入各种状态的方法u掌握线程的优先级掌握线程的优先级u掌握线程安全掌握线程安全u掌握线程同步机制掌握线程同步机制u掌握线程间的通信掌握线程间的通信访扁破翅栗你敏毕遇叁钠滩稠社后刀踌澳徒黑蓉酚诊继顽推蔼穗沈如瘟烈第16章多线程第16章多线程第第16章章多线程多线程n n1、线程简介、线程简介n n2、实现线程的两种方法、实现线程的两种方法n n3、线程的生命周期、线程的生命周

2、期n n4、操作线程的方法、操作线程的方法n n5、线程的优先级、线程的优先级n n6、线程同步、线程同步n n7、线程间的通信、线程间的通信主要内容主要内容位舍愚巫伞绝副垢冒把垫更创腕搜鸦哆限港千桩巍丸峭攘嘿荐浚厕漆蒸迎第16章多线程第16章多线程16.1线程简介线程简介n世间万物会同时完成很多工作:世间万物会同时完成很多工作:例如人体同时进行呼吸、血液循环、思例如人体同时进行呼吸、血液循环、思考问题等活动;考问题等活动;用户既可以使用计算机听歌,也可以使用户既可以使用计算机听歌,也可以使用它打印文件,用它打印文件,n而这些活动完全可以而这些活动完全可以同时进行同时进行,这种思想在,这种思想

3、在Java中被称为中被称为并发并发,而将并发完成的每一件,而将并发完成的每一件事情称为事情称为线程线程。汗荐磅氦杭卓知圭更讶匿雷恋陛玻晰髓捣穗溺呆癌紫匡务邯才敢彦蚂亿址第16章多线程第16章多线程16.1线程简介线程简介n在人们的生活中,并发机制非常重要,在人们的生活中,并发机制非常重要,但是但是并不是所有的程序语言都支持线程并不是所有的程序语言都支持线程。n在以往的程序中,多以一个任务完成后再进在以往的程序中,多以一个任务完成后再进行下一个项目的模式进行开发,这样下一个行下一个项目的模式进行开发,这样下一个任务的开始必须等待前一个任务的结束。任务的开始必须等待前一个任务的结束。nJava语言

4、提供语言提供并发机制并发机制,程序员可以在程序,程序员可以在程序中执行中执行多个线程多个线程,每一个线程完成,每一个线程完成一个功能一个功能,并与其他线程并与其他线程并发执行并发执行,这种机制被称为,这种机制被称为多多线程线程。扭食住睬篓架炭趋殉掖无蛹刨奎戒游躁批冶议叙升藏蜒翟诌舞卖的誓醛冲第16章多线程第16章多线程16.1线程简介线程简介nJava中的多线程在每个操作系统中的运行中的多线程在每个操作系统中的运行方式也存在差异,在此着重说明多线程在方式也存在差异,在此着重说明多线程在Windows操作系统操作系统的运行模式。的运行模式。nWindows操作系统是多任务操作系统,它操作系统是多

5、任务操作系统,它以进程为单位。以进程为单位。n一个进程是一个包含有自身地址的程序,每一个进程是一个包含有自身地址的程序,每个独立执行的程序都称为进程,也就是正在个独立执行的程序都称为进程,也就是正在执行的程序。执行的程序。奉眺陷策僵励蚌耕悟验蔚童歼型磐朵析细姻臀眉嫁疽曳垛孺菇贮痴乾沿刁第16章多线程第16章多线程16.1线程简介线程简介n进程进程是一个用来描述处于动态运行状态的应是一个用来描述处于动态运行状态的应用程序的概念,即一个进程就是用程序的概念,即一个进程就是一个执行中一个执行中的程序的程序,每个进程都有一块自己,每个进程都有一块自己独立的地址独立的地址空间空间,并可以包含,并可以包含

6、多个线程多个线程。这些线程将。这些线程将共共享享进程的地址空间及操作系统分配给这个进进程的地址空间及操作系统分配给这个进程的资源。程的资源。n线程线程一般是指进程中的一般是指进程中的一个执行流一个执行流,多线程,多线程是指在一个进程中是指在一个进程中同时运行多个同时运行多个不同线程,不同线程,每个线程分别执行每个线程分别执行不同的任务不同的任务。嘉卿韵圣吭搁柄塔疆汕兰腋索蓟吏函枯玄捍球戮弹鸽陪机划汛剩壤饼菲尚第16章多线程第16章多线程16.1线程简介线程简介n系统可以分配给每个进程系统可以分配给每个进程一段有限的使用一段有限的使用CPU的时间的时间(也可以称为(也可以称为CPU时间片时间片)

7、,),CPU在这段时间中执行某个进程,然后下一在这段时间中执行某个进程,然后下一个时间片又跳至另一个进程中去执行。个时间片又跳至另一个进程中去执行。n由于由于CPU转换较快,所以使得每个进程好像转换较快,所以使得每个进程好像是是同时执行同时执行一样。一样。锗丢贷绸德煌莹想险硷胰盟枕毒价甚妒提鹃党辱若跋尝戊交唤把镐督虚判第16章多线程第16章多线程16.1线程简介线程简介n一个线程则是进程中的执行流程,一个线程则是进程中的执行流程,一一个进程个进程中可以同时包括多个线程中可以同时包括多个线程,每个线程也可以,每个线程也可以得到得到一小段程序的执行时间一小段程序的执行时间,这样一个进程,这样一个进

8、程就可以具有就可以具有多个并发执行的线程多个并发执行的线程。n在单线程中,程序代码按调用顺序依次往下在单线程中,程序代码按调用顺序依次往下执行,如果需要一个进程执行,如果需要一个进程同时同时完成多段代码完成多段代码的操作的操作,就需要产生多线程。,就需要产生多线程。唐逾漓猾闽洱奶蜗民决烘瘸宇裔切爸臃拎雹竿浪毒叶呀逃赎列烬厢凶肇凝第16章多线程第16章多线程16.2实现线程的两种方式实现线程的两种方式n16.2.1继承继承Thread类类n16.2.2实现实现Runnable接口接口迂澈癌镣婶庙羌睫滓爪叶的铀用杠蓬毡篮嫡慧巢翟币佬井悄人颠落恐辅孩第16章多线程第16章多线程16.2.1继承继承T

9、hread类类nThread类是类是java.lang包中的一个类,从这包中的一个类,从这个类中实例化的对象代表线程,个类中实例化的对象代表线程,程序员启动程序员启动一个新线程需要建立一个新线程需要建立Thread实例。实例。nThread类中常用的两个构造方法如下:类中常用的两个构造方法如下:publicThread(StringthreadName);publicThread();其中第一个构造方法是创建一个名称为其中第一个构造方法是创建一个名称为threadName的线程对象。的线程对象。巨移姚派宦粥簇久材哀碑肝茶腥蜂馈垣访省山券垂盟乞尽念膊状聊将躬赫第16章多线程第16章多线程16.2

10、.1继承继承Thread类类n继承继承Thread类创建一个新的线程的语法如下:类创建一个新的线程的语法如下:publicclassThreadTestextendsThread/.助威例胎毋留柄字幅脖缸斟蝶约恃惭杂加讨旅纪陈桐断跨约报久阿沂踩糠第16章多线程第16章多线程16.2.1继承继承Thread类类n如果需要创建线程应该先定义一个如果需要创建线程应该先定义一个Thread类类的子类的子类,并且,并且覆盖覆盖其中的其中的run()成员方法成员方法,将,将线程执行的程序代码写在其中。线程执行的程序代码写在其中。nThread对象需要一个对象需要一个任务任务来执行,任务是指来执行,任务是指

11、线程在启动时执行的工作,该工作的功能代线程在启动时执行的工作,该工作的功能代码被写在码被写在run()方法中。方法中。渗淄商盂冕义淖驻仙增情骂辐尼挞剪仇添催仰壹新港沂表受奈审炉间沾蕴第16章多线程第16章多线程16.2.1继承继承Thread类类n这个这个run()方法必须使用如下这种语法格式:方法必须使用如下这种语法格式:publicvoidrun()/.注意:尽管在注意:尽管在Thread的子类中覆盖了的子类中覆盖了run()成员方法,但用户不能直接调用它,而成员方法,但用户不能直接调用它,而是需要通过调用是需要通过调用Thread类中的类中的start()方法方法间接地使用它。间接地使用

12、它。魁兽冶宅渠步脂日波术具抠凤菌江州苛值执起右残亮粤盆黍泞充去拢旋嗡第16章多线程第16章多线程16.2.1继承继承Thread类类注意注意n1)start()方法的调用后方法的调用后并不是立即执行并不是立即执行多线多线程代码,而是使得该线程变为程代码,而是使得该线程变为可运行态可运行态(Runnable),什么时候运行是由操作系统决,什么时候运行是由操作系统决定的。定的。n2)如果)如果start()方法调用一个方法调用一个已经启动已经启动的线程,的线程,系统将抛出系统将抛出IllegalThreadStateException异异常。常。鼻咱镀丘捻帮润恶寓雷茅疵垢洒卧濒钨拢良樊缝惧赘村淤错

13、遣柱荚决限雏第16章多线程第16章多线程16.2.1继承继承Thread类类注意注意nmain()方法线程启动由方法线程启动由Java虚拟机负责,程虚拟机负责,程序员负责启动自己的线程。语法如下:序员负责启动自己的线程。语法如下:publicstaticvoidmain(Stringargs)newThreadTest().start();檄场蜡淋泻类兔君刁碑恋贾梢腆曰疽糖镇藩藉吠准霞给菲析鳃闹行掘猎逃第16章多线程第16章多线程publicclassMyThreadextendsThreadpublicvoidrun()for(intn=1;n3;n+)for(inti=1;i4;i+)Sy

14、stem.out.print(getName()+(+i+);System.out.println();System.out.println(exitfrom+getName();创建两个线程对象,分别实现重复显示创建两个线程对象,分别实现重复显示13数数字的功能字的功能泽捉佬希趴蛀埂狭缄艘氖早幽编吞慧嗡亏减泥孺净滓巾停妻冶蓖侄沥芦花第16章多线程第16章多线程publicclassTestpublicstaticvoidmain(Stringargs)Threadt1=newMyThread();t1.setName(T1);Threadt2=newMyThread();t2.setName

15、(T2);t1.start();t2.start();System.out.println(exitfrom+Thread.currentThread().getName();exitfrommainT2(1)T1(1)T1(2)T1(3)T2(2)T1(1)T1(2)T1(3)T2(3)exitfromT1T2(1)T2(2)T2(3)exitfromT2订卧抠豺曲宁壮孤雀毫悍指荤窃掺氮痕演驻尝慌澳磕别赖侧扔银笛狠靶锈第16章多线程第16章多线程16.2.2实现实现Runnable接口接口n到目前为止,线程都是通过扩展到目前为止,线程都是通过扩展Thread类来类来创建的,如果程序员需要创建

16、的,如果程序员需要继承其他类继承其他类(非非Thread类类)并使该程序可以使用线程,就需并使该程序可以使用线程,就需要使用要使用Runnable接口接口。n实现实现Runnable接口的语法如下:接口的语法如下:publicclassMyThreadextendsObjectimplementsRunnable绷逢锐比海蚤耻慰倍浙暂呜丽蜘峦赶禄管局夫篆款汗烤陋岸蹲镀琴句赠针第16章多线程第16章多线程16.2.2实现实现Runnable接口接口n实现实现Runnable接口的程序会接口的程序会创建一个创建一个Thread对象对象,并将,并将Runnable对象与对象与Thread对象相关联。

17、对象相关联。nThread类中有如下两个构造方法:类中有如下两个构造方法:publicThread(Runnabler)publicThread(Runnabler,Stringname)这两个构造方法的参数中都存在这两个构造方法的参数中都存在Runnable实例,使用以上构造方法就可以实例,使用以上构造方法就可以将将Runnable实例与实例与Thread实例相关联。实例相关联。猩检凯滞报涕葫蒋妮让慢津瘩查竿枝焚帮肇湛涤珐移弟撼饭甲碱呈逃膊褐第16章多线程第16章多线程16.2.2实现实现Runnable接口接口n使用使用Runnable接口启动新的线程的步骤如接口启动新的线程的步骤如下:下

18、:1)建立)建立Runnable对象。对象。2)使用参数为)使用参数为Runnable对象的构造方对象的构造方法创建法创建Thread实例。实例。3)调用)调用start()方法启动线程。方法启动线程。崔寝障给碳根懈扳躺谩讳挖怀托优蝴痕壮形涕赘牛灸帮痢演烁慌渣垮毋笨第16章多线程第16章多线程16.2.2实现实现Runnable接口接口差跪恢佳拦口泌雀躇蛛掏壕眺刀曲郧珍知硅夺墅吏目袍灰坝贿地碰的璃运第16章多线程第16章多线程16.2.2实现实现Runnable接口接口n通过通过Runnable接口创建线程时首先需要编接口创建线程时首先需要编写一个写一个实现实现Runnable接口的类接口的类

19、,然后,然后实例实例化化该类的对象,这样就建立了该类的对象,这样就建立了Runnable对对象;象;n接下来使用相应的构造方法接下来使用相应的构造方法创建创建Thread实例实例;n最后使用该实例调用最后使用该实例调用Thread类中的类中的Start()方方法法启动线程。启动线程。惫什弘佣体阿朵滚鄂搀期孩截火袋盎傅撰田戚簇整购复吞岂砂紊宗亦模垫第16章多线程第16章多线程class MyThread2 implements Runnable private String name; public MyThread2(String name) this.name=name; public vo

20、id run()for(int i=1;i10;i+) System.out.println(name + 运行 : +i); 沪颗滇铜崎摘点濒控资乾疾祖盔汾师塑盈腊期腐铅涸遇画荣腊辕筒烂茧争第16章多线程第16章多线程public static void main(String args) new Thread(new MyThread2(th1).start(); new Thread(new MyThread2(th2).start(); /*MyThread2 th1=new MyThread2(th1); Thread thobj1=new Thread(th1); MyThread

21、2 th2=new MyThread2(th2); Thread thobj2=new Thread(th2); thobj1.start(); thobj2.start();*/呆佬氧玫蹦故殴丈油丧哀室弯赖尾既皋置的才逝皮酝赏狐妙吊栅辊汐酶吗第16章多线程第16章多线程16.2.2实现实现Runnable接口接口n实现实现Runnable接口比继承接口比继承Thread类所具有类所具有的优势:的优势:适合多个相同的程序代码的线程去处理适合多个相同的程序代码的线程去处理同一个资源同一个资源可以避免可以避免java中的单继承的限制中的单继承的限制增加程序的健壮性,代码可以被多个线增加程序的健壮性

22、,代码可以被多个线程共享,代码和数据独立程共享,代码和数据独立体销同噶饺嘻私夕咯摧腊搔抡郸尊氮虏盒霉纶旱亩离吾异蝗晕荚冲谋桩臼第16章多线程第16章多线程16.3线程的生命周期线程的生命周期n线程生命周期中的各种状态线程生命周期中的各种状态岩侨害稚埔括艰另驼佃宿济翅霜豹镊詹配讯霖援呢笨哪盒京镰巡傅阶掘客第16章多线程第16章多线程16.3线程的生命周期线程的生命周期n线程具有生命周期,其中包含线程具有生命周期,其中包含7种状态,分别种状态,分别为为出生状态、就绪状态、运行状态、等待状出生状态、就绪状态、运行状态、等待状态、休眠状态、阻塞状态和死亡状态。态、休眠状态、阻塞状态和死亡状态。出生状态

23、出生状态就是用户在创建线程时处于的状就是用户在创建线程时处于的状态,在用户使用该线程实例调用态,在用户使用该线程实例调用start()方方法之前线程都处于出生状态;法之前线程都处于出生状态;当用户调用当用户调用start()方法后,线程处于方法后,线程处于就绪就绪状态状态(又被称为可执行状态);(又被称为可执行状态);当线程得到系统资源后就进入当线程得到系统资源后就进入运行状态运行状态。君书尚袄位寸才信啃乍彰椿悄爬褥官丙乓书祖尼牺排虐磋佐叼凝移饭粥厅第16章多线程第16章多线程16.3线程的生命周期线程的生命周期n一旦线程进入可执行状态,它会在就绪与运一旦线程进入可执行状态,它会在就绪与运行状

24、态下辗转,同时也有可能进入行状态下辗转,同时也有可能进入等待、休等待、休眠、阻塞或死亡状态眠、阻塞或死亡状态。n当处于运行状态下的线程调用当处于运行状态下的线程调用Thread类中的类中的wait()方法方法,该线程处于等待状态,进入等待状,该线程处于等待状态,进入等待状态的线程必须调用态的线程必须调用Thread类中的类中的notify()方方法法才能被唤醒,而才能被唤醒,而notifyAll()方法方法是将所有是将所有处于等待状态下的线程唤醒;处于等待状态下的线程唤醒;贿梦埠偏刃砍扇兽惺繁卿俘意黎渭泉舀真还韶共星船赃拆吭植颜醚嚷鸯揪第16章多线程第16章多线程16.3线程的生命周期线程的生

25、命周期n当线程调用当线程调用Thread类中的类中的sleep()方法方法,则,则会进入会进入休眠状态休眠状态。n如果一个线程在运行状态下发出如果一个线程在运行状态下发出输入输入/输出请输出请求求,该线程将进入,该线程将进入阻塞状态阻塞状态,在其等待输入,在其等待输入/输出结束时线程进入输出结束时线程进入就绪状态就绪状态,对于阻塞的,对于阻塞的线程来说,即使系统资源空闲,线程依然不线程来说,即使系统资源空闲,线程依然不能回到运行状态;能回到运行状态;n当线程的当线程的run()方法方法执行完毕时,线程进入执行完毕时,线程进入死死亡状态亡状态。踊秸闽居胸涨蚤渔翔琐驭颠古宏珊腿邢念下矾灭湍股摄审譬

26、此匡掂缉勺釉第16章多线程第16章多线程16.3线程的生命周期线程的生命周期n虽然多线程看起来像同时执行,但事实上虽然多线程看起来像同时执行,但事实上在在同一时间点上只有一个线程被执行同一时间点上只有一个线程被执行,只是线,只是线程之间切换较快,所以才会使人产生线程是程之间切换较快,所以才会使人产生线程是同时进行的假象。同时进行的假象。n在在Windows操作系统中,系统会为每个线程操作系统中,系统会为每个线程分配一小段分配一小段CPU时间片,一旦时间片,一旦CPU时间片结时间片结束束就会将当前线程换为下一个线程,即使该就会将当前线程换为下一个线程,即使该线程没有结束的情况下。线程没有结束的情

27、况下。跋淡广盅丛颜典介方延腿庙搅嫩域甫违圃纺对棚拄患蚕又咖榜唾熬象咐雀第16章多线程第16章多线程16.3线程的生命周期线程的生命周期n根据图根据图16-5所示,可以总结出使线程进入所示,可以总结出使线程进入阻阻塞状态塞状态有以下几种可能。有以下几种可能。调用调用sleep()方法方法。调用调用wait()方法方法。等待等待输入输入/输出输出完成。完成。疥熄堕旗到遵霖摩弧屠庐宾见朋呛酱稿叛命浆字珍翼度绣浅燃铣汪纬光蛤第16章多线程第16章多线程16.3线程的生命周期线程的生命周期n当线程处于阻塞状态后,可通过以下几种方当线程处于阻塞状态后,可通过以下几种方式使线程再次进入式使线程再次进入就绪状

28、态就绪状态。线程调用线程调用notify()方法方法。线程调用线程调用notifyAll()方法方法。线程调用线程调用interrupt()方法方法。线程的线程的休眠时间结束休眠时间结束。输入输入/输出结束输出结束。株虽薄凭售襟妇毙鞋柴谁萨至乌府咏喀唯瞪眷坊琵挣浊迅揩嚷奉风吴郭逞第16章多线程第16章多线程16.4操作线程的方法操作线程的方法n16.4.1线程的休眠线程的休眠n16.4.2线程的加入线程的加入n16.4.3线程的中断线程的中断n16.4.4线程的礼让线程的礼让亭冒泣久魏似芹抓纠消烷耍淫耘蔬品发忽理因樱玖穗冈武锦董晰咎慧昌泰第16章多线程第16章多线程16.4.1线程的休眠线程的

29、休眠n一种能控制线程行为的方法是调用一种能控制线程行为的方法是调用sleep()方法方法,sleep()方法需要一个参数用于指定该线程方法需要一个参数用于指定该线程休眠的时休眠的时间间,该时间使用毫秒为单位。,该时间使用毫秒为单位。n它通常是在它通常是在run()方法内的循环中被使用。方法内的循环中被使用。nsleep()方法的语法如下:方法的语法如下:tryThread.sleep(2000);catch(InterruptedExceptione)e.printStackTrace();躺缸晶稍脉冲览建搪腮洁偿辜弃母萧己筛戚封抽粮播泞吹凿鹃停颈建尼钡第16章多线程第16章多线程public

30、 void run() System.out.println(开始执行线程。); System.out.println(进入睡眠状态。); try Thread.sleep(3000); catch (InterruptedException e) e.printStackTrace(); System.out.println(线程结束。);币泰押挖寞品乾痛雅柜薪么猎使卿佯朱症怂硷澳傈换挎数磷硫舵毕杉俏膘第16章多线程第16章多线程16.4.2线程的加入线程的加入n如果当前某程序为多线程程序,假如存在一如果当前某程序为多线程程序,假如存在一个线程个线程A,现在需要插入线程,现在需要插入线程B,

31、并要求线程,并要求线程B先执行完毕,然后再继续执行线程先执行完毕,然后再继续执行线程A,此时,此时可以使用可以使用Thread类中的类中的join()方法方法来完成。来完成。n这就好比此时正在看电视,却突然有人上门这就好比此时正在看电视,却突然有人上门收水费,必须付完水费后才能继续看电视。收水费,必须付完水费后才能继续看电视。n当某个线程使用当某个线程使用join()方法加入到另外一个线方法加入到另外一个线程时,另一个线程会等待该线程执行完毕再程时,另一个线程会等待该线程执行完毕再继续执行。继续执行。闯蜡霜抹恩抑癸壮斡呀建脑嫩优吉菲偷雕赡舰填潘员涎翻键唁窑蜀骚脯唯第16章多线程第16章多线程1

32、6.4.2线程的加入线程的加入n为什么要用为什么要用join()方法方法在很多情况下,主线程生成并起动了子线在很多情况下,主线程生成并起动了子线程,如果子线程里要进行大量的耗时的运程,如果子线程里要进行大量的耗时的运算,算,主线程往往将于子线程之前结束主线程往往将于子线程之前结束,但是如果主线程处理完其他的事务后,需但是如果主线程处理完其他的事务后,需要用到子线程的处理结果,也就是要用到子线程的处理结果,也就是主线程主线程需要等待子线程执行完成之后再结束需要等待子线程执行完成之后再结束,这,这个时候就要用到个时候就要用到join()方法了。方法了。姐宏跺哪才讶有辕而荣桓廓傻植校挂沮勺摆器楼摩辨

33、延窍颠由抹及碟慰扦第16章多线程第16章多线程class Thread1 extends Threadprivate String name; public Thread1(String name) this.name=name; public void run() for (int i = 0; i 3; i+) System.out.println(子线程+name + 运行: + i); try sleep(int) Math.random() * 10); catch (InterruptedException e) e.printStackTrace(); 到不依涤踞蹈土初旧染幼束凑

34、厚纶懂峦凿收朔矩怀还禁撤抢坦抵十方不茶第16章多线程第16章多线程public static void main(String args) System.out.println(Thread.currentThread().getName()+ 主线程运行开始!); Thread1 mTh1=new Thread1(A); Thread1 mTh2=new Thread1(B); mTh1.start(); mTh2.start(); System.out.println(Thread.currentThread().getName()+ 主线程运行结束!); main主线程运行开始!main

35、主线程运行结束!子线程B运行 : 0子线程A运行 : 0子线程B运行 : 1子线程A运行 : 1子线程B运行 : 2子线程A运行 : 2宁瞎谅鬼文旨凰绅附味鳖链嚼惨磕锭挠思猫佩伴抢火怀睦宠酿歪浦诈烩聊第16章多线程第16章多线程public static void main(String args) Thread1 mTh1=new Thread1(A); Thread1 mTh2=new Thread1(B); mTh1.start(); mTh2.start(); try mTh1.join(); mTh2.join(); catch (InterruptedException e) e.

36、printStackTrace(); main主线程运行开始!子线程B运行 : 0子线程B运行 : 1子线程B运行 : 2子线程A运行 : 0子线程A运行 : 1子线程A运行 : 2main主线程运行结束!铬捂狭井韦腹躬韵豺饱磺漆旋枉妒辆匠辞苍腊佐姿韧撂噬鄙逝踌僵针仁拙第16章多线程第16章多线程16.4.3线程的中断线程的中断n以前使用以前使用stop()方法停止线程,但当前版本方法停止线程,但当前版本的的JDK早已废除了早已废除了stop()方法,同时也不建方法,同时也不建议使用议使用stop()方法来停止一个线程的运行。方法来停止一个线程的运行。n现在提倡在现在提倡在run()方法中使用

37、无限循环的形式,方法中使用无限循环的形式,然后使用一个布尔型标记控制循环的停止。然后使用一个布尔型标记控制循环的停止。退校汰颇割且脓闪衙副洗疲京烽喂胸蔡掏剧啸迄危戳觅够桂载灰与授针腮第16章多线程第16章多线程class ThreadTest extends Thread private int count = 10; public void run() while (true) System.out.print(count + ); if (-count = 0) return; 弱豫孜佬硫猜括怖殴轰俐生淳颤熔乓洲忆婆茂坝阻煎抗辟郝饭折蝴者潦宇第16章多线程第16章多线程16.4.4线程的礼

38、让线程的礼让nThread类中使用类中使用yield()方法方法表示礼让,它只表示礼让,它只是给当前正处于运行状态下的线程一个提醒,是给当前正处于运行状态下的线程一个提醒,告知它告知它可以将可以将资源礼让给其他线程。但这仅资源礼让给其他线程。但这仅仅是一种暗示,没有任何一种机制保证当前仅是一种暗示,没有任何一种机制保证当前线程会将资源礼让。线程会将资源礼让。n对于支持多任务的操作系统来说,不需要调对于支持多任务的操作系统来说,不需要调用用yeild()方法,因为操作系统会为线程自动方法,因为操作系统会为线程自动分配分配CPU时间片来执行。时间片来执行。阿搂景专瓢蕊乱英秦磐丙颂恫钦吵抽柬矮胰恭籍

39、绘资趁舆奥函豫健员侨奥第16章多线程第16章多线程16.5线程的优先级线程的优先级n每个线程都具有各自的优先级,线程的优先每个线程都具有各自的优先级,线程的优先级可以在程序中表明该线程的重要性,级可以在程序中表明该线程的重要性,如果如果有很多线程处于就绪状态,系统会根据优先有很多线程处于就绪状态,系统会根据优先级来决定首先使哪个线程进入运行状态级来决定首先使哪个线程进入运行状态。n但这并不意味着低优先级的线程得不到运行,但这并不意味着低优先级的线程得不到运行,而只是它运行的几率比较小,比如垃圾回收而只是它运行的几率比较小,比如垃圾回收线程的优先级就较低。线程的优先级就较低。拆能年当酵遏所免吹嗜

40、锋陌渣向魔皿跌十质耀酿瓣祝灸糯裁呜防剂陀昂驶第16章多线程第16章多线程16.5线程的优先级线程的优先级nThread类中包含的静态成员变量代表了线程类中包含的静态成员变量代表了线程的某些优先级,比如的某些优先级,比如Thread.MIN_PRIORITY(常数(常数1)、)、Thread.MAX_PRIORITY(常数(常数10)、)、Thread.NORM_PRIORITY(常数(常数5)。)。n其中每个线程的优先级都在其中每个线程的优先级都在Thread.MIN_PRIORITYThread.MAX_PRIORITY之间,在默认情况之间,在默认情况下其优先级都是下其优先级都是Thread

41、.NORM_PRIORITY。每个新产生的线程都继承了父线程的优先级。每个新产生的线程都继承了父线程的优先级。缀顽焕袜驹永替敷绕浇艾丛慰汹叹锤锋镶黑吵屡按损茸恶召章候冻苞沫芝第16章多线程第16章多线程16.5线程的优先级线程的优先级n在多任务操作系统中,每个线程都会得到一小在多任务操作系统中,每个线程都会得到一小段段CPU时间片运行,时间片运行,在时间结束时,将轮换另在时间结束时,将轮换另一个线程进入运行状态,这时系统会选择与当一个线程进入运行状态,这时系统会选择与当前线程优先级相同的线程予以运行。前线程优先级相同的线程予以运行。n系统始终选择就绪状态下优先级较高的线程进系统始终选择就绪状态

42、下优先级较高的线程进入运行状态。入运行状态。n线程的优先级可以使用线程的优先级可以使用setPriority()方法方法调整,调整,如果使用该方法设置的优先级不在如果使用该方法设置的优先级不在110之内,之内,将产生一个将产生一个IllegalArgumentException异常。异常。凛谍瘴叁籍掩戴姻谭榴啃硷馒浓犬丝聋违僳舍国缄霓透姜购双戍季泞找堪第16章多线程第16章多线程16.5线程的优先级线程的优先级腥吐矩咀陡斌肛阴替达烟缅析耐鲜诅凭汽舌妙盐哪谩逃陕曰魁伊铡人掺墟第16章多线程第16章多线程16.5线程的优先级线程的优先级n在图在图16-9中,优先级为中,优先级为5的线程的线程A首先

43、得到首先得到CPU时间片;当该时间结束后,轮换到与时间片;当该时间结束后,轮换到与线程线程A相同优先级的线程相同优先级的线程B;当线程;当线程B的运的运行时间结束后,会继续轮换到线程行时间结束后,会继续轮换到线程A,n直到线程直到线程A与线程与线程B都执行完毕,才会轮换都执行完毕,才会轮换到线程到线程C;当线程;当线程C结束后,最后才会轮到结束后,最后才会轮到线程线程D。卵矾俄俯辱壬赣检芳脱忧煽豁团驰弯飘件仑骋盈索梅完揍艳像害域依愁作第16章多线程第16章多线程class MyThread51 extends Thread public MyThread51(String name) supe

44、r(name); public void run() for (int i=0; i 0) try Thread.sleep(100); catch (Exception e) e.printStackTrace(); System.out.println(tickets+num-); 豢岗烹赁如梯弃怎去凄杀穆泵悟鲜鸿铡澜冷搀玖善豢尹帝谎腋传旭票敝冶第16章多线程第16章多线程 public static void main(String args) ThreadSafeTest t = new ThreadSafeTest(); Thread tA = new Thread(t); / 以该

45、类对象分别实例化4个线程 Thread tB = new Thread(t); Thread tC = new Thread(t); Thread tD = new Thread(t); tA.start(); / 分别启动线程 tB.start(); tC.start(); tD.start(); tickets10tickets8tickets9tickets7tickets6tickets4tickets5tickets6tickets3tickets2tickets1tickets0tickets-1tickets-2铭陶刨皿邹换奴充秒桶舵脏蛹恼遏央猛钥染烙登虐诸柒务烁雁扮堡矢殆酮第1

46、6章多线程第16章多线程16.6.2线程同步机制线程同步机制n如何解决资源共享的问题?如何解决资源共享的问题?基本上所有解决多线程资源冲突问题都会基本上所有解决多线程资源冲突问题都会采用给定时间只采用给定时间只允许一个线程访问共享资允许一个线程访问共享资源源,这时就需要给共享资源上一道锁。,这时就需要给共享资源上一道锁。为了解决多线程并发操作可能引起的数据为了解决多线程并发操作可能引起的数据混乱,在混乱,在java中,引入对象中,引入对象“互斥锁互斥锁”,以,以保证共享数据操作的完整性。保证共享数据操作的完整性。倚效疯床境辫哥抬添霞肛骤掳鹤时敛适妓靶谩拖虞斯沤钾偶渡庸钮趣靡懦第16章多线程第1

47、6章多线程16.6.2线程同步机制线程同步机制1)同步块同步块n在在Java中提供了同步机制,可以有效地防止中提供了同步机制,可以有效地防止资源冲突。资源冲突。n同步机制使用同步机制使用synchronized关键字。关键字。synchronized(Object)赏贮秉犊猾劝涤秸樊帧招陌噶樊籍飘靳蔑翰飞妙久疹寂疫安鲁篆蛛梧稀爱第16章多线程第16章多线程nObject为任意一个对象为任意一个对象,每个对象都存在一个每个对象都存在一个标志位标志位,并具有两个值并具有两个值,分别为分别为0和和1。n一个线程运行到同步块时首先检查该对象的标一个线程运行到同步块时首先检查该对象的标志位,如果为志位,

48、如果为0状态,表明此同步块中存在其状态,表明此同步块中存在其他线程在运行。他线程在运行。n这时该线程就处于就绪状态,直到这时该线程就处于就绪状态,直到处于同步块处于同步块中的线程执行完同步块中的代码为止。中的线程执行完同步块中的代码为止。n这时该对象的标识位被设置为这时该对象的标识位被设置为1,该线程才能,该线程才能执行同步块中的代码,并将执行同步块中的代码,并将Object对象的标对象的标识位设置为识位设置为0,防止其他线程执行同步块中的,防止其他线程执行同步块中的代码。代码。豪危粮帮炊啪掇九泥巴薄中捶袄莆适转翟姥香孔坤苑掳妙逾仇懈糠源贯痕第16章多线程第16章多线程 public void

49、 run() synchronized () while (num 0) try Thread.sleep(100); catch (Exception e) e.printStackTrace(); System.out.println(tickets+num-); 勿宠梁驳奸其炭吵赛骇僧狈匹渣犹牡轴绎逢窑趴帜影哦秩姥禾欺酗概京捡第16章多线程第16章多线程16.6.2线程同步机制线程同步机制2)同步方法同步方法n同步方法就是在方法前面修饰同步方法就是在方法前面修饰synchronized关键字的方法,其语法如下。关键字的方法,其语法如下。synchronizedvoidf()n当某个对象调

50、用了同步方法,该对象上的其当某个对象调用了同步方法,该对象上的其他同步方法必须等待该同步方法执行完毕才他同步方法必须等待该同步方法执行完毕才能被执行。必须将每个能访问共享资源的方能被执行。必须将每个能访问共享资源的方法修饰为法修饰为synchronized,否则就会出错。,否则就会出错。篇鸡撵筑越程趋求橡溢赛井惑侗戎裸检骂云舌阳祥温侍剩琅蜒柏捅屋伸坷第16章多线程第16章多线程16.6.2线程同步机制线程同步机制n无论无论synchronized关键字加在方法上还是关键字加在方法上还是对象上,它取得的对象上,它取得的锁都是对象锁都是对象,而不是把一,而不是把一段代码或函数当作锁。段代码或函数当

51、作锁。n每个对象只有一个锁(每个对象只有一个锁(lock)与之相关联。)与之相关联。n实现同步是要很大的系统开销作为代价的,实现同步是要很大的系统开销作为代价的,甚至可能造成甚至可能造成死锁死锁,所以尽量避免无谓的同,所以尽量避免无谓的同步控制。步控制。盘殉残饥钟弄淡鼓彪惠疵谁至宜姥赏卸型赚铰尽棍鼠钻破漱棠氨吴广绅仁第16章多线程第16章多线程16.7线程间的通信线程间的通信n线程之间的通信使用线程之间的通信使用wait()、notify()以及以及notifyAll()方法实现。方法实现。n线程调用线程调用wait()方法后可以使该线程从运行方法后可以使该线程从运行状态进入就绪状态状态进入就

52、绪状态,sleep()方法也达到这样方法也达到这样一个效果,那么两者究竟有何区别?一个效果,那么两者究竟有何区别?n从同步的角度上来说,调用从同步的角度上来说,调用sleep()方法的线方法的线程不释放锁,但调用程不释放锁,但调用wait()方法的线程释放方法的线程释放锁。锁。衙峨灵制副凿坟均逛淖定与象崇伞饱盟掌蛤棒常忿燃喇蓄厉豁疯寐爸舜未第16章多线程第16章多线程16.7线程间的通信线程间的通信n使用使用wait()方法有以下两种形式:方法有以下两种形式:wait(time)wait()第一种形式的第一种形式的wait()方法与方法与sleep()方法的含方法的含义相同,都是指在此时间之内

53、暂停;义相同,都是指在此时间之内暂停;而第二种形式的而第二种形式的wait()方法会使线程永久无方法会使线程永久无限地等待下去,需要使用限地等待下去,需要使用notify()或者或者notifyAll()方法唤醒。方法唤醒。叼稿庶兔誊铆佣废满针乾吾话责沂蛤狐蔫册妙偿篙讥液缎村狐娶秤料掺墓第16章多线程第16章多线程16.7线程间的通信线程间的通信nnotify()方法用来唤醒一个处于阻塞状态的线方法用来唤醒一个处于阻塞状态的线程,任何一个已经满足了被唤醒条件的线程程,任何一个已经满足了被唤醒条件的线程都可能被唤醒。都可能被唤醒。nnotifyAll()方法可以唤醒所有处于等待状态方法可以唤醒所

54、有处于等待状态的线程。的线程。鳞遇倘陵卢逃迎慷惠事酵然鞠擞过纬批羔尔歧簿寒酣代兜溉府整柏频王莆第16章多线程第16章多线程wait和和sleep区别区别n共同点:共同点:1.他们都是在多线程的环境下,都可以在他们都是在多线程的环境下,都可以在程序的调用处阻塞指定的毫秒数,并返回。程序的调用处阻塞指定的毫秒数,并返回。2.wait()和和sleep()都可以通过都可以通过interrupt()方法方法打断线程的暂停状态打断线程的暂停状态,从而使线程,从而使线程立刻抛出立刻抛出InterruptedException。拘柞葬怖橱虎竿凹炬俊狭啄案首览氨伍翔潮碧厄郊姻陀枪瑶脑挞呢者巴甄第16章多线程第

55、16章多线程wait和和sleep区别区别n如果线程如果线程A希望立即结束线程希望立即结束线程B,则可以对线,则可以对线程程B对应的对应的Thread实例调用实例调用interrupt方法。方法。如果此刻线程如果此刻线程B正在正在wait/sleep/join,则线程,则线程B会立刻抛出会立刻抛出InterruptedException,在,在catch()中直接中直接return即可安全地结束线程。即可安全地结束线程。营菏烁赋迢仰搬弄沫篆茫实查瓜姑骡肇胯式依草悔屉帮差遏藐候粒诀般掷第16章多线程第16章多线程wait和和sleep区别区别n不同点:不同点:1.Thread类的方法:类的方法:

56、sleep(),yield()等等Object的方法:的方法:wait()和和notify()等等2.每个对象都有一个锁来控制同步访问。每个对象都有一个锁来控制同步访问。Synchronized关键字可以和对象的锁交互,关键字可以和对象的锁交互,来实现线程的同步。来实现线程的同步。sleep方法没有释放锁,而方法没有释放锁,而wait方法释放方法释放了锁,使得其他线程可以使用同步控制块了锁,使得其他线程可以使用同步控制块或者方法。或者方法。颅着婚链晦仇庭幕吻寥钢腐揭架狰搅他吨匈偶窥软饲登末敦阂呆灶茶马毫第16章多线程第16章多线程wait和和sleep区别区别n不同点:不同点:3.wait,notify和和notifyAll只能在同步控只能在同步控制方法或者同步控制块里面使用,而制方法或者同步控制块里面使用,而sleep可以在任何地方使用可以在任何地方使用4.sleep必须捕获异常,而必须捕获异常,而wait,notify和和notifyAll不需要捕获异常不需要捕获异常兼店愈炉爷焙智馒况答乡嘲压漱抨阎烁名郝闹伞态灭孕经驹巳浦数折煌权第16章多线程第16章多线程

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 建筑/环境 > 施工组织

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