java课件第10节课 线程_第1页
java课件第10节课 线程_第2页
java课件第10节课 线程_第3页
java课件第10节课 线程_第4页
java课件第10节课 线程_第5页
已阅读5页,还剩16页未读 继续免费阅读

下载本文档

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

文档简介

线程,区分程序、进程和线程程序是一段静态的代码,它是应用软件执行的蓝本进程是程序的一次动态执行过程,它对应了从代码加载、执行至执行完毕的一个完整过程,这个过程也是进程本身从产生、发展至消亡的过程线程是比进程更小的执行单位,一个进程在其执行过程中,可以产生多个线程,形成多条执行线索,每条线索,即每个线程也有它自身的产生、存在和消亡的过程,也是一个动态的概念。,线程的种类每个Java程序都有一个缺省的主线程。当JVM加载代码,发现main方法之后,就会启动一个线程,这个线程称作“主线程”,该线程负责执行main方法。在main方法的执行中再创建的线程,就称为程序中的其它线程。线程切换机制如果main方法中又创建了其他线程,那么JVM就要在主线程和其他线程之间轮流切换,保证每个线程都有机会使用CPU资源。main方法即使执行完最后的语句,JVM也不会结束我们的程序,JVM一直要等到程序中的所有线程都结束之后,才结束我们的Java应用程序,创建线程定义一个类继承Thread类在该类中要重写父类的run方法,在此方法中写线程启动后要执行的代码生成该类的对象,让该对象调用Thread类的start方法,就可以启动线程了Start方法执行后,线程进入就绪状态,表示线程开始排队,等待cpu分配时间片。线程排队采用竞争方式(不是谁先start就轮到谁,而是排队的线程一起抢)。每次cpu分给每个线程的时间是随机的。,Thread类方法getId()getName()run()getPriority()interrupt()会打断正在睡眠的线程,让它抛出异常isAlive()isInterrupt()setName()sleep()start(),publicclasslx1publicstaticvoidmain(Stringargs)输出数字sc1=new输出数字();输出字母sc2=new输出字母();sc1.start();sc2.start();class输出数字extendsThreadpublicvoidrun()for(inti=1;i=300;i+)System.out.println(线程输出数字+i);class输出字母extendsThreadpublicvoidrun()for(inti=0;i=127;i+)System.out.println(线程输出字母+(char)i);,继承Thread类来创建线程的实例,创建线程定义一个类实现Runnable接口在该类中要重写run方法定义一个Thread类对象,将该类的对象作为构造函数的参数。下图显示了Thread类的所有构造函数,其中有一个构造函数就是将Runnable对象作为参数的。,publicclasslx2publicstaticvoidmain(Stringargs)Threadsc1=newThread(new输出数字();Threadsc2=newThread(new输出字母();sc1.start();sc2.start();class输出数字implementsRunnablepublicvoidrun()for(inti=1;i=300;i+)System.out.println(线程输出数字+i);class输出字母implementsRunnablepublicvoidrun()for(inti=0;i=127;i+)System.out.println(线程输出字母+(char)i);,实现Runnable接口来创建线程的实例,将所有的线程写到同一个类中要在一个Thread的子类中区分出不同的线程,就要给不同的线程取名,然后利用Thread类的方法得到名字,再用if语句进行判断要用到的Thread类的currentThread函数和getName函数,还要用到String类的equals函数,publicstaticThreadcurrentThread()返回对当前正在执行的线程对象的引用。,publicfinalStringgetName()返回该线程的名称。,publicbooleanequals(ObjectanObject)将此字符串与指定的对象比较。当且仅当该参数不为null,并且是与此对象表示相同字符序列的String对象时,结果才为true。,publicclasslx3publicstaticvoidmain(Stringargs)输出sc1=new输出(输出数字);输出sc2=new输出(输出字母);sc1.start();sc2.start();class输出extendsThread输出(Strings)setName(s);/调用父类的setName方法,设置线程的名字publicvoidrun()if(Thread.currentThread().getName().equals(输出数字)for(inti=1;i=300;i+)System.out.println(线程输出数字+i);elsefor(inti=0;i=127;i+)System.out.println(线程输出字母+(char)i);,在同一类中写不同线程的代码,线程的生命周期新建的线程在它的一个完整的生命周期中通常要经历4种状态,新建(即生成一个Thread类对象后,此时仅仅分配了内存空间)运行。线程调用了Start方法后并没有进行运行状态,而是进入了线程队列,当JVM为线程分配了CPU后,线程才进入了运行状态中断JVM将CPU资源从当前线程切换给其他线程,使本线程让出CPU的使用权处于中断状态。线程使用CPU资源期间,执行了sleep(intmillsecond)方法,使当前线程进入休眠状态。线程使用CPU资源期间,执行了wait()方法,使得当前线程进入等待状态。等待状态的线程不会主动进到线程队列中排队等待CPU资源,必须由其他线程调用notify()方法通知它,使得它重新进到线程队列中排队等待CPU资源,以便从中断处继续运行。线程使用CPU资源期间,执行某个操作进入阻塞状态,比如执行读/写操作引起阻塞。进入阻塞状态时线程不能进入排队队列,只有当引起阻塞的原因消除时,线程才重新进到线程队列中排队等待CPU资源,以便从原来中断处开始继续运行。死亡。处于死亡状态的线程不具有继续运行的能力。线程死亡的原因有二,一个是正常运行的线程完成了它的全部工作,即执行完run方法中的全部语句,结束了run方法。另一个原因是线程被提前强制性地终止,即强制run方法结束。,线程的同步大多数需要运行多线程的应用程序中,两个或多个线程需要共享同一个数据的访问。如果每个线程都会调用一个修改数据状态的方法,那么这些线程将会互相影响对方的运行。为了避免多个线程同时访问一个共享数据,必须掌握如何对访问进行同步,线程的同步publicclassXC1implementsRunnableintn=20;Booleanf=true;publicvoidrun()while(f)tryjian();catch(InterruptedExceptionex)Logger.getLogger(XC1.class.getName().log(Level.SEVERE,null,ex);publicvoidjian()throwsInterruptedExceptionif(n=0)f=false;return;System.out.println(Thread.currentThread().getName()+n-);Thread.sleep(100);publicstaticvoidmain(Stringargs)XC1xc=newXC1();Threadt1=newThread(xc,黄牛);Threadt2=newThread(xc,代理);Threadt3=newThread(xc,官网);t1.start();t2.start();t3.start();,1、此程序没有进行同步2、每次运行结果不一定相同3、3个线程使用同一个变量n4、在该程序中线程的切换有2种方式,第一种是jian方法没执行完cup就切到其他线程了,第二种是本线程主动sleep,cpu会将时间片分配给其他线程5、当第一种情况出现时会出错,线程的同步publicclassXC2implementsRunnableintn=20;Booleanf=true;publicvoidrun()while(f)tryjian();catch(InterruptedExceptionex)Logger.getLogger(XC1.class.getName().log(Level.SEVERE,null,ex);publicsynchronizedvoidjian()throwsInterruptedExceptionif(n=0)f=false;return;System.out.println(Thread.currentThread().getName()+n-);Thread.sleep(100);publicstaticvoidmain(Stringargs)XC2xc=newXC2();Threadt1=newThread(xc,黄牛);Threadt2=newThread(xc,代理);Threadt3=newThread(xc,官网);t1.start();t2.start();t3.start();,改正的方法1、只需在jian方法前加上关键字synchronized,表示给jian方法加把锁2、当某个线程在执行jian方法时,还没执行完,cpu就把时间片切换到下一线程,由于上一线程没执行完,这个方法还没解锁,其他线程即使得到时间片也无法执行,cpu再次切换,最后只有切换到被它打断的线程,程序才能继续执行3、这样就可以保证线程在执行同步方法时一定要把它的代码执行完,下一线程才可以再执行这个方法,多个加了互斥锁的方法,importjava.util.logging.Level;importjava.util.logging.Logger;publicclassXC9implementsRunnableintn=0;intmt=0;Booleanflag=true;publicvoidrun()tryif(Thread.currentThread().getName().equals(厨师)sc();elsexf();catch(Exceptione)e.printStackTrace();publicsynchronizedvoidsc()throwsInterruptedExceptionfor(inti=0;i=9;i+)mt+;Thread.sleep(500);System.out.println(厨师生产了第+mt+馒头);publicsynchronizedvoidxf()throwsInterruptedExceptionfor(inti=0;i=9;i+)Thread.sleep(200);System.out.println(食客消费了第+mt+馒头);publicstaticvoidmain(Stringargs)XC9xc=newXC9();Threadt1=newThread(xc,厨师);Threadt2=newThread(xc,食客);t1.start();t2.start();,用Synchnized关键字修饰方法,表示给此方法加把锁,告诉cpu此方法没有结束的时候,cpu不要打断它,此处有sleep语句,告诉cpu想休息一会,cpu也不会把时间切给其他线程,如何能够控制线程的切换呢?线程的挂起和恢复所谓挂起线程就是让线程暂时让出cpu的使用权限,停止执行。由于挂起的时间不定,因此不能用sleep方法。挂起线程就是让需要挂起的线程调用wait方法所谓恢复线程就是其他的线程在执行完自己的操作后通过notifyAll或notify方法唤醒所有调用了wait方法的线程,使得挂起的线程重新执行。注意:wait、notify和notifyAll方法都必须写到sychronized方法中,利用wait、notify、notifyAll实现线程交替运行,importjava.util.logging.Level;importjava.util.logging.Logger;publicclassXC5implementsRunnableintn=0;intmt=0;Booleanflag=true;publicvoidrun()tryif(Thread.currentThread().getName().equals(厨师)sc();elsexf();catch(Exceptione)e.printStackTrace();publicsynchronizedvoidsc()throwsInterruptedExceptionfor(inti=0;i=9;i+)if(!flag)this.wait();mt+;Thread.sleep(500);System.out.println(厨师生产了第+mt+馒头);flag=false;this.notify();publicsynchronizedvoidxf()throwsInterruptedException,for(inti=0;i=9;i+)if(flag)this.wait();Thread.sleep(200);System.out.println(食客消费了第+mt+馒头);flag=true;this.notify();publicstaticvoidmain(Stringargs)XC5xc=newXC5();Threadt1=newThread(xc,厨师);Threadt2=newThread(xc,食客);t1.start();t2.start();,互斥锁除了锁方法外,还可以锁对象,importjava.util.logging.Level;importjava.util.logging.Logger;publicclassXC10implementsRunnableintn=0;intmt=0;Objectobj=newObject();Booleanflag=true;publicvoidrun()tryif(Thread.currentThread().getName().equals(厨师)sc();elsexf();catch(Exceptione)e.printStackTrace();publicvoidsc()throwsInterruptedExceptionsynchronized(obj)for(inti=0;i=5;i+)if(!flag)obj.wait();mt+;Thread.sleep(500);System.out.println(厨师生产了第+mt+馒头);flag=false;obj.notify();,publicvoidxf()throwsInterruptedExceptionsynchronized(obj)for(inti=0;i=5;i+)if(flag)obj.wait();Thread.sleep(200);System.out.println(食客消费了第+mt+馒头);flag=true;obj.notify();publicstaticvoidmain(Stringargs)XC10 xc=newXC10();Threadt1=newThread(xc,厨师);Threadt2=newThread(xc,食客);t1.start();t2.start();,示例一个线程发送52个数字,4个线程依次接收13个数字设置发送线程Sender的优先级最高位1,保证接收线程每执行1次,再由发送线程执行1次4个接收线程的优先级默认为5,为区别该轮由哪个线程来接收数字,在缓冲区设置表示顺序的信号量sort,值为0-3为了程序设计的简单,先将界面设计为网格布置的4个文本区,每个文本区对应1个线程,该文本区对应线程接收到的所有的数字接收线程在顺利取得1个数字后,唤醒其他所有等待的线程,由于发送线程的优先级高,它将立刻执行;发送线程发送了一个数字后,唤醒其他所有等待的4个接收线程,线程序号和sort值相等的接收线程将执行。,作业设计一个程序包含5个线程,1个发牌线程,4个接收线程,发牌线程负责将已经打乱的52张牌发送到内容区,4个接收线程依次从内容区各自取出13张牌。设计一个窗体,里面包含4个内部窗体,在每个内部窗体中显示1个接收线程得到的牌分析在“扑克牌线程.java”程序中,为了设计简单,我们用数字来模拟52张牌,因此只用JTextArea(文本区)就可以显示接收线程接收到的牌了。为了更直观地显示4个玩家接收到的牌,我们还是用按钮来表示每张牌,为了能同时看到4个玩家接收到的牌,因此想到用内部窗体来显示每个玩家接收的牌,这样就要设计一个窗体,里面包含4个内部窗体,每个内部窗体又显示13张牌按钮。,线程的同步,importjava.util.concurrent.locks.Lock;importjava.util.concurrent.

温馨提示

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

评论

0/150

提交评论