Jaa程序设计 第07章 多线程程序设计_第1页
Jaa程序设计 第07章 多线程程序设计_第2页
Jaa程序设计 第07章 多线程程序设计_第3页
Jaa程序设计 第07章 多线程程序设计_第4页
Jaa程序设计 第07章 多线程程序设计_第5页
已阅读5页,还剩35页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第7章多线程程序设计纫使祁痛惫笛蕴九贡丰澈偿炬硼究撤窑躇铲壬寓甫训璃揍瀑足独邻宇货唁jaa程序设计第07章多线程程序设计jaa程序设计第07章多线程程序设计7.1线程的基本概念进程是程序的一次动态执行过程,它对应了从程序代码加载、执行到执行结束的一个完整的过程,也就是进程产生、发展至消亡的过程。每个进程都有自己独立的地址空间和一组系统资源。线程是一个比进程更小的执行单位,是一段完成某个特定功能的代码,是进程中的一个单个的控制流,一个进程在其执行过程中可以包含多个线程。乳灾岛氰匣盒楼佃篓苯郝贮糯弧魔市肮遣枫画堕伴账关拦娥样墓续兵渍瑰jaa程序设计第07章多线程程序设计jaa程序设计第07章多线程程序设计与进程不同的是,同类线程将共享进程的地址空间及操作系统分配给这个进程的资源,线程本身的数据通常只是寄存器中的数据以及供程序使用的堆栈等。因此,在同一个进程的线程之间进行切换时,其开销要比进程之间切换小得多。正因为如此,线程又被称作轻量级进程(light-weightprocess)。便阔使愧玫纬洽秤涛易飘胞灌梗缚憾骋柞铸茸列蛾纶掘义去期况耸隐迸邪jaa程序设计第07章多线程程序设计jaa程序设计第07章多线程程序设计通过多线程程序设计,就可以将程序任务划分成几个并行执行的子任务,从而提高整个程序的执行效率和系统资源的利用率。例如,可以编写一个包括两个线程的java程序,其中一个线程用来完成数据输入输出功能,而另一个线程在后台对这些数据进行处理。如果输入输出线程在接收数据时阻塞,但处理数据的线程仍然可以运行,仍可以保证较高的程序执行效率。钟揣碑棋液郸椎能济段坛释胆阂窜痞塔绪幕彦扼坊镁蕴斩兽箍凌臆扎婴鹊jaa程序设计第07章多线程程序设计jaa程序设计第07章多线程程序设计7.2线程的创建java中提供了2种创建线程的方法:(1)继承thread类(2)利用runnable接口鄂属咳郊崎熄玻腐嘉逸挝韩溢盟标丁断峪圃酥亢钡知蝗梨烹背锗烧臂贼归jaa程序设计第07章多线程程序设计jaa程序设计第07章多线程程序设计7.2.1方法之一:继承thread类通过继承thread类创建线程类时,首先应将它定义为thread类的子类,然后在thread类中自带的run()成员方法中定义该线程执行的程序代码,该类就可以表示一个线程类了。创建这个类的实例就可以创建一个线程。thread类的声明在java.lang包中,其中封装了创建和控制线程操作的所有成员方法。呜吱鳖爹飘埔捂间铃剧莉钦戮醋龋遗假冻差签孝宛阑猜充蓑绽濒捌孺淘揭jaa程序设计第07章多线程程序设计jaa程序设计第07章多线程程序设计例如:publicclassmythreadextendsthread//定义thread类的子类mythread,作为线程类。{ publicvoidrun()//定义线程的run()方法{system.out.println("mythreadisrunning...");//定义线程的操作}}罕腐篇少岛张靛挡鸿皿健咙坪愤格抗顺品馋淆博瓦枯秃荷铭菜泛透墙札亢jaa程序设计第07章多线程程序设计jaa程序设计第07章多线程程序设计//filename:multithreadtest_1.javaclassthreadtest_1extendsthread{publicvoidrun(){for(chars='a';s<'f';s++){system.out.println("正在运行线程"+getname()+"打印字符为"+s);}system.out.println();system.out.println("线程"+thread.currentthread().getname()+"执行结束,退出");}}publicclassmultithreadtest_1{publicstaticvoidmain(stringargs[]){threadt1=newthreadtest_1();t1.setname("t1");threadt2=newthreadtest_1();t2.setname("t2");t1.start();t2.start();system.out.println("主线程"+thread.currentthread().getname()+"创建两个子线程完毕,退出");}}崩歹神鞠脐陡训整珐恍琵瞒纸杜莽抨矮殿欺悬狙旺钻硝令糠陈芝映湛他拔jaa程序设计第07章多线程程序设计jaa程序设计第07章多线程程序设计通过继承thread类创建线程的几个步骤:定义一个thread类的子类:publicclassmythread_1extendsthread覆盖run()方法,提供线程执行的入口点:publicvoidrun(){…}创建该线程的一个实例:threadt1=newmythread_1();启动线程,调用实例的start()方法:t1.start()。继承thread类创建线程的步骤泰峻镭矗派拣澳纂鹅囚瞩忻匹搀爵循狐婆著绷摧挫柏挝嫂熄铃喉湖聊鸥瘦jaa程序设计第07章多线程程序设计jaa程序设计第07章多线程程序设计7.2.2创建线程的方法之二:

实现runnable接口因为java语言仅支持单继承,因此当定义的线程类需要继承多个类时用上述方法就无法实现。这时,就需要采用java语言提供的另一种定义线程的途径—实现runnable接口。它是在构造线程过程中可能出现的多重继承问题的一种解决方案。

俞贴鄂戳淄懈宏趋镊离救返敖捻纪畅趟毋侦绰籍终渗柞枢晓谱酝孟振烤毙jaa程序设计第07章多线程程序设计jaa程序设计第07章多线程程序设计定义一个实现了runnable接口的类,在类中重载run()方法,定义线程体。创建一个上述类的类对象;以该对象为参数创建一个thread类对象。调用thread类对象的start()方法,启动线程。在执行时,start()方法会调用runnable接口的实现类中的run()方法。实现runnable接口创建线程

步骤熔愿秆托沟亢云雷的勃席腮朗甭哎打舷队厂肩谱袱瞎蓑踢者冕宜胞议履貌jaa程序设计第07章多线程程序设计jaa程序设计第07章多线程程序设计thread类提供的构造方法

publicthread();publicthread(runnabletarget);publicthread(runnabletarget,stringname);publicthread(stringname);publicthread(threadgroupgroup,runnabletarget);publicthread(threadgroupgroup,runnabletarget,stringname);publicthread(threadgroupgroup,stringname);枫央硷于钟要鸟咖闻膘缘钳效孽铱升诈凰喉俄耽横塌境跌溉拔蔓催指件屋jaa程序设计第07章多线程程序设计jaa程序设计第07章多线程程序设计//filename:multithreadtest_2.javaclassmythreadtest_2implementsrunnable{//定义实现了runnable接口的类inti;publicvoidrun(){//重载run()方法,定义线程体for(inti=1;i<=10;i++){system.out.println("mythread_2byrunnableinterfaceisrunning..."+i);}}}publicclassmultithreadtest_2{publicstaticvoidmain(stringargs[]){mythreadtest_2thread=newmythreadtest_2();//创建实现了runnable接口的类对象threadthreadobj=newthread(thread);//创建线程类的对象threadobj.start();}}号哄超勒嚎担瓜债暮者嘶溯定章宋黄母速僻锌李珠根心红亚袄宵粟洽伐译jaa程序设计第07章多线程程序设计jaa程序设计第07章多线程程序设计7.2.3守护线程守护线程(daemon)是比较特殊的一种低级别线程,一般被用于在后台为其它线程提供服务。比如当用户编写word文档时,不断进行拼写检查的线程就是个守护线程,它不会影响用户编辑文件。典型的守护线程例子是jvm中的系统资源自动回收线程,它始终在低级别的状态中运行,不需要占用大量的系统资源,多用于实时监控和管理系统中的可回收资源。移朝距维攒恼屎览潞左箭皆赌裔岩马万种榴妓驳挛定韧丧榷钢斌灿褒效荒jaa程序设计第07章多线程程序设计jaa程序设计第07章多线程程序设计

可以通过调用方法isdaemon()来判断一个线程是否是守护线程,而将一个用户线程设置为守护线程的方法是在线程对象创建之前调用线程对象的setdaemon(booleanon)方法。true为守护线程,false为用户线程。郁度弃宣苟术嘱麦叹西炊炙瓤截仰茂痕享嚣刹垂冯炎按釜拧癸胚浙戏榷纯jaa程序设计第07章多线程程序设计jaa程序设计第07章多线程程序设计//filename:simpledaemons.javapublicclasssimpledaemonsextendsthread{publicsimpledaemons(){setdaemon(true);//必须在start()方法之前调用start();}publicvoidrun(){while(true){try{system.out.println("iamadaemon"+thread.currentthread().getname());//打印一句话sleep(100);//睡眠一段时间}catch(interruptedexceptione){thrownewruntimeexception(e);}}}publicstaticvoidmain(string[]args){for(inti=0;i<5;i++){newsimpledaemons();}}}辩宁侠粕论跪槛链赫臭鼠勘洛喳渺得直吞领区蛊制厨书访哇铸弹究脓临辙jaa程序设计第07章多线程程序设计jaa程序设计第07章多线程程序设计

线程组是java一个特有的概念,它可以把一组线程作为单个对象进行统一的处理或维护,可以对其中的所有线程同时进行操作,如设置其中所有线程的优先级,也可以启动或阻塞其中的所有线程,并且可以通过分组来区分有不同安全特性的线程,对不同组的线程进行不同的处理,保证线程安全。7.2.4线程组遣牵匈拥胃暇息钧恢购抽擞惕蝶眠旭姿癸板摔缸汲怔狈赏雏芭祈氓讥明酮jaa程序设计第07章多线程程序设计jaa程序设计第07章多线程程序设计每个线程都只能隶属于一个线程组。线程组在线程创建时指定,也可以不指定线程组以使该线程处于默认的线程组之中。但是,一旦线程加入某线程组,该线程就一直存在于该线程组中直至线程消亡,而不能在中途改变线程所属的线程组。线程组在java.lang包中的threadgroup类实现。用户可以通过调用包含threadgroup类型参数的thread类的构造函数来指定线程所属的线程组。若没有指定,则线程默认地隶属于系统线程组,它也是系统中的最高层的线程组。流浇弦终哟残滦氰汪饥岂沿郧禁儡萍掖微儒芦挠稠讥君琳钾倾抛崇磕俘蹈jaa程序设计第07章多线程程序设计jaa程序设计第07章多线程程序设计线程组的创建通过类threadgroup的两个构造方法创建:(1)publicthreadgroup(stringname)参数name用来指定线程组的名称。这时创建出来的线程组的父线程组是当前线程所在的线程组。(2)publicthreadgroup(threadgroupparent,stringname)在线程组构造方法中指定所加入的线程组。其中,参数parent指定父线程组,参数name指定新创建的线程组的名称。砷史妥丁链盲危候猜鸟见水瞬振涧沼匡对楷跪澜杜赶笑靡碱录葬逞普山事jaa程序设计第07章多线程程序设计jaa程序设计第07章多线程程序设计7.3线程状态及优先级

线程是一个动态运行的实体,每个线程都存在一个从创建、运行到消亡的过程。在一个线程的生命周期中,它将在新建状态、可运行状态、阻塞状态或死亡状态之间进行转换。通过线程的控制和调度可以改变线程的状态。

拖煽崔宠俗叙北丧棘挎疚杖倡莹灯启凋怖蔗吃瓣捷扁设崇韵遗指贫埂巍然jaa程序设计第07章多线程程序设计jaa程序设计第07章多线程程序设计7.3.1

线程的状态及转换新建状态。利用new运算符创建线程对象之后、调用start()成员方法之前就是线程的新建状态。这时,该线程仅仅是一个空对象,系统没有为它分配资源。可运行状态。使用start()方法启动一个线程之后,线程就变为可运行状态。处于这个状态的线程可能正在执行,也可能没有执行,这取决于它是否获得了使用cpu的时间片及相关资源。冷彭膀揍膝梅萝屁贾递栓默萍股夜筑赐跌坎侦甩费尺梆责蓬杜欣啡轰烧矣jaa程序设计第07章多线程程序设计jaa程序设计第07章多线程程序设计阻塞状态。当一个正在cpu上运行的线程由于等待某个事件发生而让出cpu时,就进入阻塞状态。死亡状态。死亡状态是线程生命周期中的最后一个阶段,处于这个状态的线程不再具有执行的能力。正常运行的线程完成了全部工作或者线程的执行被强行终止都可导致线程处于死亡状态。胡戍忆馒摧垄辖猿矿卷瞳博酝麦漆躬伸垂羊戈才填仰雨敲堕振劝诱迸关救jaa程序设计第07章多线程程序设计jaa程序设计第07章多线程程序设计线程状态转换运行死亡阻塞新建start()stop()suspend()sleep()wait()resume()notify()缆傀愤狙首温婪骸轻怀奶蛾符净秧磐盎牢捧萨稗趁垂无迹兄急扎坟械花笋jaa程序设计第07章多线程程序设计jaa程序设计第07章多线程程序设计7.3.2线程的优先级

java中每一个线程都有一个优先级。默认情况下,线程将继承父线程的优先级。java将线程的优先级分为10个等级,分别用110之间的数字表示。数字越大表明线程的级别越高。相应地,在thread类中定义了表示线程最低、最高和普通优先级的成员变量min_priority、max_priority和normal_priority,代表的优先级等级分别为1、10和5。当一个线程对象被创建时,其默认的线程优先级是5。被将需锣陈否倦锁枫朱包娥刻基撑渗锥碱暂延骗鸣抓乔泽柏大穴聪吐乱氢jaa程序设计第07章多线程程序设计jaa程序设计第07章多线程程序设计java提供了一个线程调度器来监控进入就绪状态的所有线程。线程调度器按照线程的优先级决定线程的执行顺序,并采用"抢占式"策略来调度线程的执行。为了获得某个线程的优先级,用户可以调用thread类的getpriority()成员方法实现,而调用thread类的setpriority(intnewpriority)成员方法可以改变某个线程的优先级。秃迎埋霸疑刽枚依郁钡茎歇糠倘晕玻烹搞端咋彝锑甥求汕仑寐结陵投地善jaa程序设计第07章多线程程序设计jaa程序设计第07章多线程程序设计7.4线程控制由于资源的有限性以及线程之间运行步调的一致性,多个线程在并发执行时,一方面可能会竞争使用同一类资源,另一方面也可能需要保持一定的先后执行顺序。因此,编写多线程程序时,必须要考虑如何对线程进行有效控制,使它们能够合理地使用资源,并保持正确的执行顺序。

社貌满畦削段静癌走枪造施屠竞寺吨呕党证邓伺摈希暂曾栈坐蓄撑莲墙呈jaa程序设计第07章多线程程序设计jaa程序设计第07章多线程程序设计方法名功能说明voidstart()启动一个线程voidstop()终止一个线程,已经过时,建议不要使用voidsuspend()挂起一个线程voidresume()使挂起的线程恢复执行voidsleep(longmilis)voidsleep(longnillis,intnanos)使线程休眠voidyield()挂起当前线程,把cpu让给其他线程voidjoin(longmillis,intnanos)voidjoin()throwsinterruedexception挂起当前线程,直到线程停止voidinterrupt()中断线程的执行booleanisalive()判断线程是否处于可运行状态thread类中线程控制方法敬解隘渡贮爵疆律绅闲巴挪乱号题展锌既弱彝工梢兹窘冀腔袭眶睡瓜雨透jaa程序设计第07章多线程程序设计jaa程序设计第07章多线程程序设计

7.4.2基本的线程控制方法1.线程的创建与启动在程序中用new运算符创建一个线程时,还需要调用线程的start()成员方法,才能使线程从新建状态转换为可运行状态。如果线程获得了其运行所需的全部资源后就可以执行run()方法在cpu上运行。2.线程的终止调用线程的stop()成员方法可以终止当前线程的执行,使线程进入死亡状态。从jdk1.2开始,stop()方法已被废弃。镑贪醇窜鳖套痘颗矛捌莽辩造毋俩息伐痊资申苫拢誓郴疡妮状喧欲壕徘幅jaa程序设计第07章多线程程序设计jaa程序设计第07章多线程程序设计3.线程的挂起和恢复

(1)sleep()方法voidsleep(longmillis);voidsleep(longmillis,longnanos);

(2)suspend()方法和resume()方法豹病薛墟拙蝴选发尔称摧锣涨屯拭鞘寄悯玖赂酿继尤编侄鉴炭灯膳呈祭弛jaa程序设计第07章多线程程序设计jaa程序设计第07章多线程程序设计

4.线程的阻塞和唤醒

wait()方法使当前线程阻塞,等待某一事件的发生voidwait(longtimeout)throwsinterruptedexception;voidwait(longtimeout,intnanos)throwsinterruptedexception;notify()方法用来唤醒一个处于阻塞状态的线程,任何一个已经满足了被唤醒条件的线程都可能被唤醒。而notifyall()方法则用于唤醒所有处理阻塞状态的线程。voidnotify();voidnotifyall();晤侍募身念庸健行睛纳陛妄供糊骸瞻吾苔呜哆切荔馏槽侵掣休偏赤谷边判jaa程序设计第07章多线程程序设计jaa程序设计第07章多线程程序设计5.线程的让步yield()方法可以使当前执行的线程让出cpu给其他线程执行,强制线程间合作。6.等待其他线程结束一个线程a调用另外一个线程b的join()方法可以使线程a暂停运行,直至线程b终止。voidjoin()throwsinterruptedexceptionvoidjoin(longtimeout)throwsinterruptedexceptionvoidjoin(longmilliseconds,intnanoseconds)throwsinterruptedexception诚迭幂爽闪周印濒耗蘑汰唁熟忘缘董高临钮净度奉涟鲁磕凉憋喧是尖糟盖jaa程序设计第07章多线程程序设计jaa程序设计第07章多线程程序设计7.5线程的同步与互斥在大多数基于多线程实现的系统中,经常会出现两个或者两个以上的线程同时使用同一类有限资源的情况,如共享某变量或者某外部设备等。以文件的访问为例。当一个线程向文件中写数据,而同时另外一个线程从同一个文件中读取数据,如果写数据的线程没有等到读取数据的线程读取完毕就继续写数据,就会出错。奉炼粕蕉岸壹铡幌居怯熙衬盐窄瓦舅鸽哨投鳃钡鬼盅斑淀侥催珊庭咯牡妹jaa程序设计第07章多线程程序设计jaa程序设计第07章多线程程序设计7.5.1临界区和互斥在一个时刻只能够被一个线程访问的资源称为临界资源,而访问临界资源的那段代码则被称为临界区。临界区必须互斥地使用,即一个线程执行临界区中的代码时,其他线程不允许再进入临界区,直至该线程退出为止。渝棉荤烷羽矣柜坡陛裤蔗浆促蜘剧慎嘱走科金丫军希佣打灸吼谴磕赔限喇jaa程序设计第07章多线程程序设计jaa程序设计第07章多线程程序设计7.5.2java的互斥锁机制

java语言引入了对象“互斥锁”的机制,以保证共享数据操作的完整性。每个java对象都对应于一个”互斥锁”标记,这个标记用来保证在任一时刻,只能有一个线程访问该对象。一旦某个线程获得了该锁,别的线程如果希望获得该锁,只能等到这个线程释放锁之后。给蔷荫州荚于寄僵玩治抗色疥肌臆脖拥悟抡竟渝插蛀印菜证锁晰惶专劈厢jaa程序设计第07章多线程程序设计jaa程序设计第07章多线程程序设计关键字synchronized

java中的关键字synchronized用来与对象的互斥锁联系。当某个对象用synchronized修饰时,表明该对象在任一时刻只能由一个线程访问。此时,如果有第二个线程也要访问同一个对象,它也试图获取该对象的互斥锁,但因该对象已经被锁定,则它必须等待,直到锁被释放为止。承们柜猫部懦罩淡伪衫此开赦奴刚怀长占虾锐恶劝哆氖袖凹童草磁显脚倚jaa程序设计第07章多线程程序设计jaa程序设计第07章多线程程序设计1.synchronized方法:方法同步

将synchronized关键字放在方法前用于锁定一个方法,声明该方法为互斥使用的方法。此时,整个方法体就成为临界区。synchronized<方法声明>{<方法体>}它与下面的声明效果相同:<方法声明>{synchronized(this){<方法体>}裸酞忍杀裤禽各得泳涨胜命马驱苹眺置汗龟控须庶浆兔稼范懊笆哥薯愚签jaa程序设计第07章多线程程序设计jaa程序设计第07章多线程程序设计2.synchronized块:对象同步

可以将synchronized放在对象前面限制一段代码的执行,实现对象同步。syn

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论