您好,欢迎访问三七文档
第16章多线程教学目标:Java线程的概念Java多线程编程方法线程的控制教学难点:线程资源的同步处理Java语言的一个重要特性是支持多线程的程序设计,多线程是实现并发的一种有效手段线程是一个能独立执行自身指令的控制流一个程序中可以同时运行多个相对独立的线程,这样的程序称为多线程程序操作系统将CPU的执行划分为非常小的时间片,根据一定的规则在不同的线程之间切换,使每个线程都得到执行的机会1、多线程的概念2.进程与线程进程(Process)是应用程序在内存环境中基本的执行单元。在Java中,进程是有不同的地址空间且处在可执行状态中的应用程序。线程(Thread)是指进程中某个单一的顺序控制流程。进程与线程的重要区别之一在于线程不能够单独执行,它必须运行在处于活动状态的应用程序进程中;每个进程都可以同时有执行不同任务的多个线程。2.进程与线程线程与进程区别之二在于二者的通信不同。进程可以创建子进程,父子进程拥有不同的可执行代码和数据内存空间,因此进程间通信复杂,可能需要管道、消息队列、共享内存或信号处理来保证进程间的通信,不仅费时而且有限。而一个进程中的各线程因为共享地址空间,所以它们之间的通信是非常简单而有效的,线程仅是过程调用,它们彼此独立执行,拥有独立的执行堆栈和程序执行上下文。3、线程的状态4、Java采用抢占式调度策略下面几种情况下,当前线程会放弃CPU:(1)当前时间片用完;(2)线程在执行时调用了yield()或sleep()方法主动放弃;(3)进行I/O访问,等待用户输入,导致线程阻塞;或者为等候一个条件变量,线程调用wait()方法;(4)有高优先级的线程参与调度。线程的优先级用数字来表示,范围从1~10。主线程的默认优先级为5Thread.MIN_PRIORITY=1Thread.MAX_PRIORITY=10Thread.NORM_PRIORITY=55、优先级策略优先级高的先执行,优先级低的后执行多线程系统会自动为每个线程分配一个优先级,缺省时,继承其父类的优先级任务紧急的线程,其优先级较高同优先级的线程按“先进先出”的原则Thread类中几个常用的有关优先级的方法:VoidsetPriority(intnewPriority)//重置线程优先级IntgetPriority()//获得当前线程的优先级6、Thread构造方法publicThread(ThreadGroupgroup,Runnabletarget,Stringname);publicThread();publicThread(Runnabletarget);publicThread(Runnabletarget,Stringname);publicThread(Stringname);publicThread(ThreadGroupgroup,Runnabletarget);publicThread(ThreadGroupgroup,Stringname);指明了线程所属的线程组是线程体run()方法所在的对象,必须实现接口Runnable线程的名称7、Thread类的主要方法方法功能CurrentThread()返回当前运行的Thread对象start()启动线程run()由调度程序调用,当run()方法返回时,该线程停止sleep(intn)使线程睡眠n毫秒,n毫秒后,线程可以再次运行isAlive()测试线程是否处于活动状态。interrupt()中断线程。interrupted()测试当前线程是否已经中断。isInterrupted()测试线程是否已经中断。yield()将CPU控制权主动移交到下一个可运行线程setName(String)赋予线程一个名字getName()取得由setName()方法设置的线程名字的字符串getPriority()返回线程优先级setPriority(int)设置线程优先级join()当前线程等待调用该方法的线程结束后,再往下执行。setDaemon(boolean)设置该线程是daemon线程还是用户线程,Daemon线程也称服务线程,通常编成无限循环,在后台持续运行。类Object的两个方法:voidwait():在其他线程调用此对象的notify()方法或notifyAll()方法前,导致当前线程等待。Voidwait(longtimeout):在其他线程调用此对象的notify()方法或notifyAll()方法,或者超过指定的时间量前,导致当前线程等待。Voidwait(longtimeout,intnanos):在其他线程调用此对象的notify()方法或notifyAll()方法,或者其他某个线程中断当前线程,或者已超过某个实际时间量前,导致当前线程等待。类Object的两个方法:Voidnotify():唤醒在此对象监视器上等待的单个线程。VoidnotifyAll():唤醒在此对象监视器上等待的所有线程。8、创建线程和执行线程(方法1)从Thread类派生出一个子类,在类中一定要实现run()classLefthandextendsThread{publicvoidrun(){……}}Lefthandleft=newLefthand();left.start();然后用该类创建一个对象用start()方法启动线程(Fig16.3)8、创建线程和执行线程(方法2)Thread的构造方法中包含有一个Runnable实例的参数,必须定义一个实现Runnable接口的类并产生一个该类的实例,对该实例的引用就是适合于这个构造方法的参数publicclassxyzimplementsRunnable{inti;publicvoidrun(){while(true){System.out.println(Hello+i++);}}}Runnabler=newxyz();Threadt=newThread(r);9、线程的调度(1)sleep()是静态方法,可以通过Thread.sleep(x)直接引用–x指定了线程再次启动前必须休眠的最小时间,毫秒为单位–可能引发中断异常InterruptedException,因此要进行捕获和处理–“最小时间”是因为这个方法只保证在一段时间后线程回到就绪态,至于它是否能够获得CPU运行,则要视线程调度而定,所以,通常线程实际被暂停的时间都比指定的时间要长。9、线程的调度(2)yield():强制终止线程的执行,使相同优先级而当前处于等待状态的其他线程获得运行机会。可以给其他同等优先级线程一个运行的机会如果在就绪队列中有其他同优先级的线程,yield()把调用者放入就绪队列尾,并允许其他线程运行;如果没有这样的线程,则yield()不做任何工作。sleep()调用允许低优先级进程运行,而yield()方法只给同优先级进程以运行机会9、线程的调度(3)join():使当前线程等待所调用线程结束。Voidjoin():等待该线程终止Voidjoin(longmillis):等待该线程终止的时间最长为millis毫秒。Voidjoin(longmillis,intnanos):等待该线程终止的时间最长为millis毫秒+nanos纳秒。publicvoidtimeout(){//暂停该线程,等候其他线程结束tt.join();//其他线程结束后,继续执行该线程…………}(MethodTest.java)10、线程组线程组类ThreadGroup提供了按组管理线程的机制,它又是线程的一种安全机制,它保证同组线程不能互相影响。PublicThreadGroup(Stringname)PublicThreadGroup(ThreadGroupparent,Stringname)线程组中的操作与线程Thread中的操作基本相同,惟一不同的就是线程组的操作都是针对该线程组中的所有线程对象。例如:ThreadGroupg=newThreadGroup(MyGroup);Runnabler=newGrp();Threadt1=newThread(g,r);Threadt2=newThread(g,r);生产者和消费者问题是从操作系统中的许多实际数据通讯与同步问题中抽象出来的具有代表性的问题。它反映了操作系统中典型的通信与同步情况。由于生产者进程与消费者进程彼此独立,两者运行的速度具有随机性。很可能出现消费者所需的信息生产者没有提供,或者相反生产者已经产生的信息消费者来不及接收。保证这种临界资源的准确使用至关重要。(fig16_04_08)10、未同步情况下的生产者/消费者12、同步情况下的生产者/消费者Java提供了互斥锁的同步机制来保护临界区。临界区是一次仅允许一个线程访问的代码段。Java引入关键字synchronized来定义临界区,它有两种用法:synchronized方法和synchronized块。当某个线程进入临界区后,系统将给临界区加锁,其他线程则无法再进入临界区,只能等到该线程退出临界区,即开锁后方可进入,从而实现线程的同步。线程间的同步操作是通过线程同步语句synchronized和Java.lang.object类中提供的线程间的通信方法wait()、notify()、notifyall()及采用内部监视器的手段来实现同步数据的访问。线程同步有同步方法和同步语句两种。(1)同步方法在方法的声明中用synchronized关键字修饰,可以对该方法中的所有代码实现同步。格式如下:publicsynchronizedvoidmethod(){…}(2)同步语句用synchronized关键字修饰的程序块称同步语句或同步块。当需要调用某个类中的方法,而该类没有同步方法,但又必须实现同步时,就要采用同步语句。只要将对这个类定义的方法的调用放入一个synchronized块内就可以了。相应格式如下:synchronized(object){…}其中,object是对同步对象的引用。(fig16_09_10)13、生产者/消费者关系:循环缓冲区类SwingUtilities的方法:staticvoidinvokeAndWait(RunnabledoRun):导致doRun.run()在AWT事件指派线程上同步执行。staticvoidinvokeLater(RunnabledoRun):导致doRun.run()在AWT事件指派线程上异步执行。invokeLate和invoteAndWait,它们都使事件派发线程上的可运行对象排队。当可运行对象排在事件派发队列的队首时,就调用其run方法。invokeLater在把可运行的对象放入队列后就返回,而invokeAndWait一直等待知道已启动了可运行的run方法才返回。(fig16_11_15)14、守护线程在客户/服务器模式下,服务器的作用是持续等待用户发来的请求,并按请求完成客户的工作。此时用到守护线程(Daemon)守护线程具有最低的优先级,守护线程是为其它线程提供服务的线程,它一般应该是一个独立的线程,它的run()方法是一个无限循环。守护线程是唯一运行着的线程时,程序会自动退出。典型的守护线程例子是JVM中的系统资源自动回收线程,即垃圾收集线程。客户端服务器端requestdaemon14、守护线程相关主要方法:publicbooleanisDaemon()–确定一个线程是否是守护线程publicvoidsetDaemon(boolean)–调用setDaemon(true)方法,可以使线程成为守护线程(必须在start之前调用)–调用setDaemon(false)方法,可以使线程成为一般线程(必须在start之前调用)
本文标题:JAVA多线程.
链接地址:https://www.777doc.com/doc-2880888 .html