Java第七章多线程机制.ppt
Java程序设计,多线程机制,内容,线程的概念多线程的实现方法线程的状态和生命周期线程的调度与优先级线程的同步机制,线程的概念,程序:静态的,计算机语言编写的代码。进程:动态的,程序的一次执行过程;每一个进程有独立的内存空间和系统资源。多进程:操作系统中多个程序同时执行。线程:程序中单个顺序的流控制,是最小的执行单位;同类的多个线程共享一块内存空间和一组系统资源;线程独享的资源只有:寄存器,系统堆栈。多线程:程序中多个片断同时执行。,多线程的实现方法(1),扩展类创建一个新类来扩展Thread类,然后再创建该类的实例。当一个类继承Thread时,它必须覆盖父类的run()方法,这个run()方法是新线程的入口。调用start()方法启动新线程执行。,class Mythread extends Thread public void run()/*覆盖父类的方法*/,多线程的实现方法(2),实现接口创建一个实现Runnable 接口的类,该接口中只有一个方法:public void run();已实现的run方法称为线程体,而实现了Runnable接口的对象称为线程的目标对象将实现了Runnable接口的类的实例作为Thread类构造函数的参数创建线程对象,调用该对象的start()方法启动线程,,class Mythread implements Runnable public void run()/*实现该方法*/,多线程实现示例,Thread1.javaRunnable1.java注意:两个线程交替运行。外观上显现出并发的特性。后启动的线程可能先执行,运行结果具有不确定性。即,线程启动后并不是马上运行,是否运行取决于系统调度。main本身也是一个线程。,Thread类,类声明:构造方法public Thread()public Thread(Stringname)public Thread(Runnabletarget)public Thread(Runnabletarget,Stringname)类方法public static Thread currentThread()public static int activeCount()public static int enumerate(Threadtarray),public class Thread implements Runnable.,实例方法public final String getName()public final void setName(Stringname)public void start()public final boolean isAlive(),两种创建线程方法的比较,继承Thread类:简单,但由于Java只允许单重继承,因此不能再继承其他的类实现Runnable接口:当一个线程已继承了其他类时,只能采用实现Runnable接口的方法来创建线程。,线程的状态和生命周期(1),线程的生命周期:线程从创建、运行到消亡的过程线程的状态:线程处在生命期的阶段。创建就绪运行阻塞死亡,创建,就绪,阻塞,运行,死亡,线程的状态和生命周期(2),创建:使用new创建线程对象后处于创建状态,此时系统没有为它分配运行资源。可运行状态:使用start()方法启动一个线程后系统分配除CPU外的资源,线程进入等待队列等候运行。运行中状态:线程占用CPU开始运行。阻塞状态:在线程等待一个事件时,就称其处于阻塞状态。三种情况导致阻塞:public static native void sleep(long millis)public final void wait()输入/输出操作死亡:run()方法结束,可以用以下方法判断线程是否死亡:public final boolean isAlive()返回true:线程已启动(可运行、运行或阻塞),false:新建或已终止,改变线程的状态,public static native void sleep(long millis)使当前线程睡眠millis毫秒public static void yield()使当前线程临时暂停执行,使得其他可运行态的同优先级线程有机会运行(使程序的运行不依赖于系统的时间片机制)public final void join()使得当前线程暂停执行,等待调用该方法的线程对象的线程结束后再继续执行当前线程。public void interrupt()为当前线程对象的线程设置中断标记,但并不中断线程的运行;若当前线程对象的线程被sleep,wait,join等方法阻塞后,调用该方法将抛出InterruptedException。(这被用于终止一个长时间处于阻塞状态的线程),改变线程的状态示例,WelcomSwing.java,线程的调度与优先级(1),Java中每一个线程用一个整数表示:110NORM_PRIORITY:值为 5MAX_PRIORITY:值为 10MIN_PRIORITY:值为 1当一个线程被创建时,他拥有创建它的线程的优先级。可使用以下方法改变线程的优先级:final void setPriority(int newp)final int getPriority()当两个线程的优先级不同时,JRE选择优先级高的运行。当两个线程优先级相同时,JRE任意选择一个。,线程的调度与优先级(2),被选择的线程将一直运行,除非:出现高优先级的可运行的线程线程转为阻塞态,或run()方法执行完毕若系统支持时间片,当时间片用完。,线程的同步机制,当多个线程需要访问共同资源时,需要考虑同步示例:Save1.java运行结果:存在问题:每个线程的run方法均可能和其他线程的run方法交叉执行解决方法:使用synchronized关键字锁定一段代码,现有0,存入100,余额100现有0,存入200,余额300现有0,取走300,余额0,关键字synchronized,两种使用方法:锁定一段代码锁定一个方法,synchronized(对象名)代码块;,synchronized 方法声明 代码块;,Java中任何class的对象都拥有一个锁,称为对象锁;任何时刻一个对象锁只能被一个线程获得;只有获得对象锁的方法才能执行该对象的synchronized方法或代码块;当一个线程,进入某一对象的synchronized方法或代码块中执行时,该线程获得此对象的锁。注意,锁定是以对象为单位若两个线程同时对一个类的两个对象进行操作时,则这两个线程可以同时执行这两个对象synchronized方法;若一个线程获得某一对象的锁,则其他任何线程均不能执行该对象的其他任何synchronized方法。,线程间的通信(1),示例:Sender1.java 输出:存在问题:线程间缺乏通信机制解决办法:使用wait,notify,和notifyAll方法,Sender put:2Sender put:3 Receiver get:3,线程间的通信(2),public final void wait()阻塞该线程的执行,并释放对象锁。注意:方法sleep(),并不释放对象锁,并且调用wait()方法的线程应该已获得该对象的对象锁。public final void notify()唤醒与该对象相关的并且由于调用了wait方法而进入了阻塞态的一个线程。注意:并且调用notify()方法的线程应该已获得该对象的对象锁。public final void notifyAll()唤醒与该对象相关的并且由于调用了wait方法而进入了阻塞态的所有线程。注意:并且调用notifyAll()方法的线程应该已获得该对象的对象锁。示例:Sender2.java,死锁,当多个线程处于等待而无法被唤醒时,构成死锁。例如:只有wait方法而没有notify方法。java既不能发现死锁,也不能避免死锁,程序员应注意死锁问题。即,避免形成环状wait和notify。,