Java软件设计基础,java是什么意思

java 4
Java软件设计基础Java线程机制 PDF文件使用"pdfFactoryPro"试用版本创建
1.Java中的多线程机制 •基本概念 –程序 •程序是为完成特定任务、用某种语言编写的一组指令的集合,指一段静态的代码。
–进程 •进程是程序的一次执行过程,是系统进行调度和资源分配的一个独立单位,每个进程都有自己独立的一块内存空间、一组系统资源。
在进程概念中,每个进程的内部数据和状态都是完全独立的。
•计算机上同时运行多个程序叫进程并发。
操作系统按照一定的策略调度各个进程执行,以便最大限度的利用计算机的各种资源。
–线程的基本概念 •线程(Thread)是进程中某个单个顺序的控制流,也被称为轻量进程(LightweightProcess)。
SchoolofComputerScienceandTechnology PDF文件使用"pdfFactoryPro"试用版本创建 •线程是进程中的实体。
一个进程可以有多个线程,一个线程必须有一个父进程。
•线程不拥有系统资源,只有运行必需的一些数据结构;它与父进程的其他线程共享该进程拥有的全部资源。
–多线程 •多线程指在单个程序中可以同时运行多个不同的线程,执行不同的任务,这是实现并发机制的一种有效手段。
•操作系统使用分时管理各个进程,按时间片轮流执行每个进程。
Java的多线程就是在操作系统每次分时给Java程序一个时间片的CPU时间内,在若干独立的可控制的线程之间切换。
SchoolofComputerScienceandTechnology PDF文件使用"pdfFactoryPro"试用版本创建 多个线程运行在多个CPU上 多个线程共享单个CPU SchoolofComputerScienceandTechnology PDF文件使用"pdfFactoryPro"试用版本创建 •线程的生命周期 –同进程一样,线程也有从创建、运行到消亡的过程,这称为线程的生命周期。
–创建状态 •用new关键字和Thread类或其子类建立一个线程对象后,该线程对象就处于创建状态,这是线程已被创建但未开始执行的特殊状态。
处于创建状态的线程是一个空的线程对象,系统不为它分配资源,但有自己的内存空间。
•创建状态的线程通过调用start()方法进入就绪状态。
SchoolofComputerScienceandTechnology PDF文件使用"pdfFactoryPro"试用版本创建 –就绪状态 •处于就绪状态的线程已经具备了运行条件,但还没有分配到CPU,因而将进入线程队列,等待系统为其分配CPU。
•线程根据自身优先级进入等待队列的相应位置。
•一旦获得CPU,线程就进入运行状态,并自动调用自己的run()方法。
–运行状态 •进入运行状态的线程顺序执行自己run()方法中的代码,直到调用其他方法而终止,或等待某资源而阻塞,或完成任务而死亡。
•运行状态表示线程拥有了对处理器的控制权,其代码正在运行,除非运行过程的控制权被另一优先级更高的线程抢占,否则这个线程将一直持续到运行完毕。
SchoolofComputerScienceandTechnology PDF文件使用"pdfFactoryPro"试用版本创建 –阻塞状态 •处于运行状态的线程在某些情况下让出CPU并暂时终止自己的运行,进入阻塞状态。
–执行了sleep()方法;–等待I/O设备等资源 •在阻塞状态的线程不能进入就绪队列,只有当引起阻塞的原因消除时才能转入就绪状态。
–睡眠时间已到–等待的I/O设备空闲 •当再次获得CPU时,从原来终止的位置开始继续运行。
•注意:若线程正在等待某个条件,那么相关联的另一个线程必须通过调用notify()或notifyAll()方法告诉正在等待的线程条件发生了变化。
SchoolofComputerScienceandTechnology PDF文件使用"pdfFactoryPro"试用版本创建 –死亡状态 •这是线程生命周期中的最后一个阶段,表示线程已退出运行状态,并且不再进入就绪队伍。
当线程的run()方法结束或由于其他原因被终止后,线程就进入消亡状态。
线程的终止分两种情况: –自然死亡 »即从线程的run()方法正常退出; –被强制性终止 »使用Thread类中的destroy()方法或()方法终止»Java系统不赞成使用destroy()方法或()方法终止线程,因为若使用不当,可能会导致程序的死锁。
–总结 SchoolofComputerScienceandTechnology PDF文件使用"pdfFactoryPro"试用版本创建 •多线程的实现方法 –多线程有两种实现方法: •通过继承创建Thread类的子类来实现;•利用Runnable接口来实现。
–当程序作为一个应用程序运行时,Java解释器为main方法启动一个线程。
当程序作为一个applet运行时,Web浏览器启动一个线程来运行applet。
–在程序中还可以创建附加的线程以执行并发的任务。
–Java中每个任务都是一个Runnable接口的实例,也称为可运行对象。
线程本质上就是实现任务的对象。
SchoolofComputerScienceandTechnology PDF文件使用"pdfFactoryPro"试用版本创建 •创建任务和线程 –创建任务 •声明一个任务类,它必须实现Runnable接口。
–Runnable接口只包含一个run方法,需要实现这个方法来告诉系统线程是如何运行的。
•一旦声明了一个任务类,就可以利用其构造方法创建一个任务。
–在线程中执行任务 •根据任务对象创建线程;•调用start方法告诉JVM该线程准备运行。
•JVM通过调用任务中的run方法执行任务。
SchoolofComputerScienceandTechnology PDF文件使用"pdfFactoryPro"试用版本创建 –线程的一些常用方法: •start()方法 –线程调用该方法启动一个线程,使之从新建状态进入就绪队列排队,一旦轮到它来使用CPU资源时,就可以脱离创建它的主线程独立开始自己的生命周期。
•run()方法 –线程的所有活动都是通过线程体run()方法来定义并实现它被调用以后所执行的操作。
–Runnable接口中的run()方法是由系统自动调用而用户程序不得引用的方法。
•sleep()方法 –使线程睡眠一段时间,单位为毫秒。
–正在运行的高优先级线程可以在它的run()方法体中调用sleep()方法来使自己放弃处理器资源而休眠一段时间,长短由sleep()方法的参数决定。
–如果线程在休眠时被打断,JVM就抛出InterruptedException异常,因此必须在try-catch语句块中调用sleep()方法。
SchoolofComputerScienceandTechnology PDF文件使用"pdfFactoryPro"试用版本创建 •isAlive()方法 –测试线程是否处于活动状态。
•interrupt()方法 –用来唤醒休眠的线程。
系统可以通过一定方式让休眠的线程分别调用interrupt()方法,导致休眠的线程发生InterruptedException异常,从而结束休眠,重新排队等待CPU资源。
•yield()方法 –把线程移到队列的尾部。
•destroy()方法 –结束线程生命周期但不做清理工作。
•()方法 –结束线程生命周期并执行清理工作。
SchoolofComputerScienceandTechnology PDF文件使用"pdfFactoryPro"试用版本创建 •线程调度与优先级 –在CPU上以某种次序执行多个线程被称为调度。
–线程调度器 •为了控制线程的运行策略,Java定义了线程调度器来监控系统中处于就绪状态的所有线程。
•线程调度器采用“抢占式”策略来按照线程的优先级决定哪个线程获取处理器投入运行。
–优先级 •Java将线程的优先级分为10个等级,用1~10表示,数字越大表示优先级越高。
•Thread类中定义了三个成员变量: –MIN_PRIORITY:最低级(1级) SchoolofComputerScienceandTechnology PDF文件使用"pdfFactoryPro"试用版本创建 –MAX_PRIORITY:最高级(10级)–NORM_PRIORITY:普通优先级(5级) •当线程对象被创建时,默认优先级是5级。
•线程可以通过调用setPriority方法改变优先级。
–抢占式调度 •时间片方式•独占方式 •实例 SchoolofComputerScienceandTechnology PDF文件使用"pdfFactoryPro"试用版本创建 –注意: •并不是在所有系统中运行Java程序时都采用时间片策略调度线程。
一个线程在空闲时应该主动放弃CPU,以使其他同优先级和低优先级的线程得到执行。
•在Java中比较特殊的一类线程是被称作守护(Daemon)线程的低级别线程,这种线程具有最低的优先级,用于为系统中的其他对象和线程提供服务。
可以通过setDaemon方法将一个线程设置为守护线程。
•JVM中的系统资源回收线程就是典型的守护线程。
SchoolofComputerScienceandTechnology PDF文件使用"pdfFactoryPro"试用版本创建
2.多线程的创建与实现•Thread类 –在默认情况下run()是空的,必须根据需要重新设计线程的run方法,再使用start方法启动线程,将执行权转交到run。
SchoolofComputerScienceandTechnology PDF文件使用"pdfFactoryPro"试用版本创建 –过程 •使应用程序继承Thread类,并且在该类的run方法中实现并发性处理过程。
–优点 •可以在子类中增加新的成员变量,使线程具有某种属性;•可以在子类中增加新的方法,是线程具有某种功能; –注意 •run()方法必须进行重写,把要在多个线程中并行处理的代码放到这个方法中。
•虽然run()方法实现了多个线程的并行处理,但不能直接调用run()方法,而是通过start()方法来调用。
在调用start()的时候,start方法会首先进行与多线程相关的初始化,然后再自动调用run()方法。
–实例 SchoolofComputerScienceandTechnology PDF文件使用"pdfFactoryPro"试用版本创建 SchoolofComputerScienceandTechnology PDF文件使用"pdfFactoryPro"试用版本创建 •Runnable接口 –Runnable接口中定义的run方法 –还可以通过向Thread()类构造方法传递一个实现了Runnable接口的对象来创建进程。
Thread类有多个构造方法,其中可以接受Runnable参数的构造方法有以下两个: –通过Runnable接口实现线程的步骤: •定义实现Runnable接口的类 SchoolofComputerScienceandTechnology PDF文件使用"pdfFactoryPro"试用版本创建 •创建实现Runnable接口的类对象•创建线程对象•启动线程 –实现接口Runnable的类仍然可以继承其他父类,例如: –实现Runnable接口的多线程应用程序框架: SchoolofComputerScienceandTechnology PDF文件使用"pdfFactoryPro"试用版本创建 –实例 SchoolofComputerScienceandTechnology PDF文件使用"pdfFactoryPro"试用版本创建 publicclassRunnableEx{ publicstaticvoidmain(Stringargs[]){ Targetfirst,second; first=newTarget("Firstthread");second=newTarget("Secondthread"); Threadone,two; one=newThread(first);two=newThread(second); one.start();two.start(); } } classTargetimplementsRunnable{Strings;publicTarget(Strings){this.s=s;System.out.println(s+"Nowbuilding");}publicvoidrun(){ FirstthreadNowbuildingSecondthreadNowbuildingFirstthreadNowrunningSecondthreadNowrunningSecondthreadNowoverFirstthreadNowover System.out.println(s+"Nowrunning"); try{ Thread.sleep(1000); }catch(InterruptedExceptione){System.out.println(e.toString());} System.out.println(s+"Nowover"); } } SchoolofComputerScienceandTechnology PDF文件使用"pdfFactoryPro"试用版本创建 •继承Thread类与实现Runnable接口的对比 –使用Runnable接口:可以将CPU、代码和数据分开,形成清晰的风格;可以从其他类继承,适用面广,保持程序风格的一致性;–直接继承Thread类:编写简单,可以直接操纵线程,但不能再从其他类继承。
SchoolofComputerScienceandTechnology PDF文件使用"pdfFactoryPro"试用版本创建 SchoolofComputerScienceandTechnology PDF文件使用"pdfFactoryPro"试用版本创建 也可以将以上模式改写如下:声明一个Thread类的子类,并实现Runnable接口。
然后在客户端程序中用 这个类生成一个对象,并调用它的start方法来启动线程。
不推荐使用以上模式,因为它将任务和任务运行的机制混在一起。
将任务从 线程中分离出来是比较好的设计。
SchoolofComputerScienceandTechnology PDF文件使用"pdfFactoryPro"试用版本创建
3.线程的同步与死锁 •线程的等待 –Java程序中的线程并发运行将共同争夺CPU资源,哪个线程抢夺到CPU资源后就开始运行。
线程之间往往会有冲突,为规避这种现象,引入线程等待的概念。
–由于线程的调度执行是按照优先级高低的顺序进行,因此可使用sleep方法让高级线程休眠一段时间使得低优先级线程有机会执行。
–暂停线程执行的方法 •sleep()方法•suspend()方法和resume()方法 –线程的暂停和恢复可通过调用suspend()方法使线程暂时由可运行状态切换到不可运行状态。
若此线程想再回到可运行状态,必须由其他线程调用resume()方法来实现。
SchoolofComputerScienceandTechnology PDF文件使用"pdfFactoryPro"试用版本创建 由于普遍认为上述两种方法和方法具有内在的不安全因素,在Java2中不提倡这些方法。
为了替代()的使用,可以通过给Thread变量赋值为null,指出要停止它的运行。
•join()方法 –表示当前线程等待调用该方法的线程结束后再恢复执行。
–一个线程A在占有CPU资源期间,可以让其他线程B调用join()方法与本线程联合,即“B.join();”,这样称A在运行期间联合了
B。
–如果线程A在占有CPU资源期间一旦联合B线程,那么A线程将立即中断运行,一直等到它联合的线程B执行完毕,A线程才再重新排队等待CPU资源。
–如果A准备联合的线程B已经结束,则“B.join();”语句将不起任何作用。
SchoolofComputerScienceandTechnology PDF文件使用"pdfFactoryPro"试用版本创建 –实例 class} ThreadEx2extendsThread{Strings;intm,i=0;ThreadEx2(Strings){this.s=s;}publicvoidrun(){try{for(i=0;i<4;i++){sleep((int)(500*Math.random()));System.out.println(s);}System.out.println(s+"finished");}catch(InterruptedExceptione){return;}}publicstaticvoidmain(Stringargs[]){ThreadEx2a=newThreadEx2("a");ThreadEx2b=newThreadEx2("b");a.start();b.start();System.out.println("mainisfinished");} SchoolofComputerScienceandTechnology PDF文件使用"pdfFactoryPro"试用版本创建 mainisfinishedabababaafinishedbbfinished School publicclassThreadJoin{publicstaticvoidmain(Stringargsp[]){TJoina=newTJoin();a.threadA.start();a.threadB.start();} }classTJoinimplementsRunnable{ ThreadthreadA,threadB; Stringcontent[]={"各就位","预备","跑"};publicTJoin(){ threadA=newThread(this);threadB=newThread(this); threadB.setName("发令员");}publicvoidrun(){ if(Thread.currentThread()==threadA){ System.out.println("等待"+threadB.getName()+"发令");
try{threadB.join();}catch(InterruptedExceptione){return;} System.out.println("开始跑!
");}elseif(Thread.currentThread()==threadB){ System.out.println(threadB.getName()+"发令:");for(inti=0;i一个线程需要修改该内容时,另一个线程也要修改该内容,系统需要对以上情况作出使当的处理。
•Java中定义了线程同步的概念,用来实现共享数据的一致性维护。
•线程同步的使用主要是保证一个进程中多个线程的协调工作,使得线程安全的共享数据,转换和控制线程的执行,保证内存的一致性。
–实现同步的方法 •在共享内存变量的方法前加上synchronized修饰符,在程序的运行中,如果某一线程调用经synchronized修饰的方法,在该线程结束此方法之前,其他所有线程都不能运行该方法,只有等待到该方法被释放为止。
SchoolofComputerScienceandTechnology PDF文件使用"pdfFactoryPro"试用版本创建 •在线程同步中要做的第一件事就是要把修改数据的方法用关键字synchronized来修饰。
–synchronized修饰符的使用 •修饰方法 •放在对象前面限制一段代码的执行 •作为类修饰符,表明该类中的方法都是synchronized的 –实例: SchoolofComputerScienceandTechnology PDF文件使用"pdfFactoryPro"试用版本创建 publicclassBankEx{publicstaticvoidmain(Stringargs[])throwsInterruptedException{BankSavebs=newBankSave();Operatoro1=newOperator(bs,"丈夫");Operatoro2=newOperator(bs,"妻子");Threadt1=newThread(o1);Threadt2=newThread(o2);t1.start();t2.start();Thread.currentThread().sleep(500);} }classBankSave{ privatestaticintmoney=1000;publicvoidadd(inti){ money=money+i;System.out.println("丈夫存入"+i+"元,余额"+money+"元");}publicvoidget(inti){if(i<=money){ money=money-i;System.out.println("妻子取走"+i+"元,余额"+money+"元");}elseSystem.out.println("余额不足");}publicintshowMoney(){returnmoney;}} SchoolofComputerScienceandTechnology PDF文件使用"pdfFactoryPro"试用版本创建 SchoolofComputerScienceandTechnology PDF文件使用"pdfFactoryPro"试用版本创建 丈夫存入1000元,余额2000元丈夫存入1000元,余额3000元丈夫存入1000元,余额4000元丈夫存入1000元,余额5000元丈夫存入1000元,余额6000元妻子取走1000元,余额5000元妻子取走1000元,余额4000元妻子取走1000元,余额3000元妻子取走1000元,余额2000元妻子取走1000元,余额1000元 •线程的死锁 –当两个或多个线程等待一个不可能满足的条件时会发生死锁。
–死锁是发生在线程间相互阻塞的现象,允许多个线程并发访问共享资源时,必须提供同步机制,然而如果对这种机制使用不当,可能会出现线程永远被阻塞的现象。
–例如两个线程分别等待对方各自占有的一个资源,就会产生死锁。
–Java本身既不能预防死锁,也不能发现死锁,只能靠程序设计上的谨慎来避免。
•线程的调度 –线程调度方法 •Java的线程同步运行会竞争资源,但是它们的任务间存在一定的关联,这就需要调度。
•Java提供了三个方法实现线程的调度和通信: SchoolofComputerScienceandTechnology PDF文件使用"pdfFactoryPro"试用版本创建 –wait():等待方法。
可让当前线程放弃监视器并进入睡眠状态,直到其他线程进入同一监视器并调用notify()方法为止。
–notify():唤醒方法。
可唤醒同一对象监视器中调用了wait()方法的第一个线程,并把它移入锁申请队列。
–notifyAll():唤醒所有线程的方法。
唤醒同一对象监视器中调用了wait()方法的所有线程,具有最高优先级的线程首先被唤醒。
–线程的调度规则 •如果两个或两个以上的线程都修改一个对象,那么把执行修改的方法定义为synchronized的,若对象更新影响到只读方法,那么只读方法应该也定义为同步的;•如果一个线程必须等待一个对象状态发生变化,那么它应该在对象内部等待,而不是在外部等待,它可以调用一个被同步的方法,并让这个方法调用wait();•每当一个方法改变某个对象的状态时,它应该调用notifyAll()方法,这给等待队列的线程提供机会来看一看执行环境是否已发生变化。
SchoolofComputerScienceandTechnology PDF文件使用"pdfFactoryPro"试用版本创建 •wait()、notify()、notifyAll()方法属于Object类而非Thread类,在使用时要仔细检查是否每个wait()方法都有相应的notify()或notifyAll()方法且作用于相同的对象。
•对于多个线程同时等待某个条件的情况,当条件满足时应该使用notifyAll()方法唤醒。
否则某些线程会一直等待下去导致死锁。
更为保险的做法是,任何情况下都使用notifyAll()方法唤醒等待的线程。
•应当区分由于得不到锁而等待的线程和由于调用了wait()方法而等待的线程。
•wait()和notify()只能在一个同步的方法或代码块内部调用,若在一个不同步的方法内调用,运行时将产生非法监视器状态异常(IllegalMonitorStateException)。
•Java中的每个类都有一个主线程。
要执行一个程序,那么这个类当中一定要有main方法,main方法就是Java类中的主线程。
–实例:模拟三人买票 •说明: SchoolofComputerScienceandTechnology PDF文件使用"pdfFactoryPro"试用版本创建 –售货员最初只有一张五元钱,电影票五元一张。
–排队的三人中,A有一张二十元人民币,B有一张十元人民币,C有一张五元人民币。
如果给售票员的钱不是零钱,而售票员又没有零钱找,那么此人必须等待,并允许后面的人买票,以便售票员获得零钱。
•分析 –A/B/C三人买票就像三个线程,每个线程必须满足以上条件(售票员有足够的找零或者提供售票员的是五元零钱)才能执行;–A/B/C三人同时只能有一人向售票员买票;不满足条件时需要等待。
SchoolofComputerScienceandTechnology PDF文件使用"pdfFactoryPro"试用版本创建 SchoolofComputerScienceandTechnology PDF文件使用"pdfFactoryPro"试用版本创建 elseif(receiveMoney==20){while(five<1||ten<1){try{ System.out.println(Thread.currentThread().getName()+"请您一旁等待");wait(); System.out.println(Thread.currentThread().getName()+"结束等待");}catch(InterruptedExceptione){ return;}}five--;ten--;twenty++; }public } System.out.println(Thread.currentThread().getName()+"给我二十元钱,售票一张,找零十五元");}notifyAll(); } classTicketEx{publicstaticvoidmain(Stringargs[]){ Cinemaa=newCinema();a.A.start();a.B.start();a.C.start();} SchoolofComputerScienceandTechnology PDF文件使用"pdfFactoryPro"试用版本创建 •思考题:等待电梯的程序 –假设电梯停靠楼层为1~8,8个楼层都有可能有人要求搭乘电梯去往目的楼层。
–电梯控制台在同一时刻只可能对一个方向(上、下)作出响应,并到达得到响应的楼层。
–再复杂一些,在响应后的某个行进方向上如果有楼层的搭乘要求符合该方向,则“顺便”完成该要求。
•如当前在8楼的电梯响应1楼的要求向下行进,如果此时4楼的向下键被按下,则在4楼停靠,顺路搭载4楼的用户。
–电梯的运行时间上的延迟可以用sleep方法完成,未得到响应的用户则通过wait来等待。
SchoolofComputerScienceandTechnology PDF文件使用"pdfFactoryPro"试用版本创建

标签: #证书 #职位 #crm #牌子 #cnc #close #care #文件