Java 2实用教程(第三版)Java多线程机制和输入输出流ppt.ppt_第1页
Java 2实用教程(第三版)Java多线程机制和输入输出流ppt.ppt_第2页
Java 2实用教程(第三版)Java多线程机制和输入输出流ppt.ppt_第3页
Java 2实用教程(第三版)Java多线程机制和输入输出流ppt.ppt_第4页
Java 2实用教程(第三版)Java多线程机制和输入输出流ppt.ppt_第5页
已阅读5页,还剩33页未读 继续免费阅读

下载本文档

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

文档简介

第章 Java多线程机制,9.1 Java中的线程 9.2 Thread的子类创建线程 9.3 使用Runable接口 9.4 线程的常用方法 9.5 GUI线程 9.6 线程同步 9.7 在同步方法中使用wait()、notify 和notifyAll()方法 9.8 挂起、恢复和终止线程 9.9 计时器线程Timer 9.10 线程联合 9.11 守护线程,9.1 Java中的线程,程序是一段静态的代码,它是应用软件执行的蓝本。 进程是程序的一次动态执行过程,它对应了从代码加载、执行至执行完毕的一个完整过程,这个过程也是进程本身从产生、发展至消亡的过程。线程是比进程更小的执行单位,一个进程在其执行过程中,可以产生多个线程,形成多条执行线索,每条线索,即每个线程也有它自身的产生、存在和消亡的过程,也是一个动态的概念。 Java的多线程就是在操作系统每次分时给Java程序一个时间片的CPU时间内,在若干个独立的可控制的线程之间切换。,每个Java程序都有一个缺省的主线程。我们已经知道, Java应用程序总是从主类的main方法开始执行。当JVM加载代码,发现main方法之后,就会启动一个线程,这个线程称作“主线程”,该线程负责执行main方法。那么,在main方法的执行中再创建的线程,就称为程序中的其它线程。如果main方法中没有创建其他的线程,那么当main方法执行完最后一个语句,即main方法返回时,JVM就会结束我们的Java应用程序。如果main方法中又创建了其他线程,那么JVM就要在主线程和其他线程之间轮流切换,保证每个线程都有机会使用CPU资源,main方法即使执行完最后的语句,JVM也不会结束我们的程序,JVM一直要等到程序中的所有线程都结束之后,才结束我们的Java应用程序,2.线程的状态与生命周期,新建 当一个Thread类或其子类的对象被声明并创建时,新生的线程对象处于新建状态。此时它已经有了相应的内存空间和其他资源。 运行 线程创建之后就具备了运行的条件,一旦轮到它来享用CPU资源时,即JVM将CPU使用权切换给该线程时,此线程的就可以脱离创建它的主线程独立开始自己的生命周期了(即run方法执行的过程)。 中断 有4种原因的中断:CPU资源从当前线程切换给其他线程、执行了sleep(int millsecond)方法、执行了wait()方法、进入阻塞状态 。 死亡 run方法结束 。,启动线程,线程创建后仅仅是占有了内存资源,在JVM管理的线程中还没有这个线程,此线程必须调用start()方法(从父类继承的方法)通知JVM,这样JVM就会知道又有一个新一个线程排队等候切换了。,9.2 Thread的子类创建线程,用Thread类或子类创建线程对象 . 编写Thread类的子类时,需要重写父类的run方法,其目的是规定线程的具体操作,否则线程就什么也不做,因为父类的run方法中没有任何操作语句。 当JVM将CPU使用权切换给线程时,如果线程是Thread的子类创建的,该类中的run方法就立刻执行。,9.3使用Runable接口,创建线程的另一个途径就是用Thread类直接创建线程对象。使用Thread创建线程对象时,通常使用的构造方法是: Thread(Runnable target) 该构造方法中的参数是一个Runnable类型的接口,因此,在创建线程对象时必须向构造方法的参数传递一个实现Runnable接口类的实例,该实例对象称作所创线程的目标对象. 当线程调用start方法后,一旦轮到它来享用CPU资源,目标对象就会自动调用接口中的run方法(接口回调) .,9.4线程的常用方法,1start() 线程调用该方法将启动线程,使之从新建状态进入就绪队列排队,一旦轮到它来享用CPU资源时,就可以脱离创建它的线程独立开始自己的生命周期了。,2run(),Thread类的run()方法与Runnable接口中的run()方法的功能和作用相同,都用来定义线程对象被调度之后所执行的操作,都是系统自动调用而用户程序不得引用的方法。系统的Thread类中,run()方法没有具体内容,所以用户程序需要创建自己的Thread类的子类,并重写run()方法来覆盖原来的run()方法。当run方法执行完毕,线程就变成死亡状态。,3sleep(int millsecond),现程占有CPU期间,执行sleep方法来使自己放弃CPU资源,休眠一段时间。休眠时间的长短由sleep方法的参数决定,millsecond是毫秒为单位的休眠时间。如果线程在休眠时被打断,JVM就抛出InterruptedException异常。因此,必须在trycatch语句块中调用sleep方法。,4isAlive(),线程处于“新建”状态时,线程调用isAlive()方法返回false。当一个线程调用start()方法,并占有CUP资源后,该线程的run方法就开始运行,在线程的run方法结束之前,即没有进入死亡状态之前,线程调用isAlive()方法返回true。当线程进入“死亡”状态后(实体内存被释放),线程仍可以调用方法isAlive(),这时返回的值是false。 一个已经运行的线程在没有进入死亡状态时,不要再给线程分配实体,由于线程只能引用最后分配的实体,先前的实体就会成为“垃圾”,并且不会被垃圾收集机收集掉 .,5currentThread(),currentThread()方法是Thread类中的类方法,可以用类名调用,该方法返回当前正在使用CPU资源的线程。,6interrupt(),intertupt方法经常用来“吵醒”休眠的线程。当一些线程调用sleep方法处于休眠状态时,一个占有CPU资源的线程可以让休眠的线程调用interrupt 方法“吵醒”自己 .,9.5 GUI线程,程序包含图形用户界面(GUI)时,Java虚拟机在运行应用程序时会自动启动更多的线程,其中有两个重要的线程:AWT-EventQuecue和AWT-Windows。AWT-EventQuecue-()线程负责处理GUI事件,AWT-Windows线程负责将窗体或组件绘制到桌面。,9.6线程同步,线程同步问题 线程同步是指几个线程都需要调用一个同步方法(使用关键字synchronized修饰的方法) 同步机制 当一个线程A使用一个synchronized修饰的方法时,其他线程想使用这个方法时就必须等待,直到线程A 使用完该方法 (除非线程A使用wait主动让出CUP资源),9.7在同步方法中使用wait()、notify 和notifyAll()方法,等待与通知 一个线程在使用的同步方法中时,可能根据问题的需要,必须使用wait()方法使本线程等待,暂时让出CPU的使用权,并允许其它线程使用这个同步方法。其它线程如果在使用这个同步方法时如果不需要等待,那么它用完这个同步方法的同时,应当执行notifyAll()方法通知所有的由于使用这个同步方法而处于等待的线程结束等待。,9.8挂起、恢复和终止线程,挂起 有时候两个线程并不是同步的,即不涉及都需要调用一个同步方法,但线程也可能需要暂时的挂起。所谓挂起一个线程就是让线程暂时让出CPU的使用权限,暂时停止执行,但停止执行的持续时间不确定,因此不能使用sleep方法暂停线程。挂起一个线程需使用wait方法,即让准备挂起的线程调用 wait 方法,主动让出CPU的使用权限. 恢复 为了恢复该线程,其它线程在占有CUP资源期间,让挂起的线程的目标对象执行notifyAll()方法,使得挂起的线程继续执行;如果线程没有目标对象,为了恢复该线程,其它线程在占有CUP资源期间,让挂起的线程调用notifyAll()方法,使挂起的线程继续执行。,9.9计时器线程Timer,使用Timer类的构造方法:Timer(int a, Object b)创建一个计时器 . 参数a的单位是豪秒,确定计时器每隔a 毫秒“震铃“一次,参数b是计时器的监视器。计时器发生的震铃事件是ActinEvent 类型事件. 当震铃事件发生时,监视器就会监视到这个事件,就会执行接口ActionListener中的方法: actionPerformed(Actionevent e)。 使用Timer类的start()方法启动计时器,即启动线程。使用stop()方法停止计时器,即挂起线程,使用restart()方法重新启动计时器,即恢复线程 .,9.10线程联合,一个线程A在占有CUP资源期间,可以让其它线程调用join()和本线程联合 . 如果线程A在占有CUP资源期间一旦联合B线程,那么A线程将立刻中断执行,一直等到它联合的线程B执行完毕,A线程再重新排队等待CUP资源,以便恢复执行。,9.11守护线程,程序中的所有用户线程都已结束运行时,即使守护线程的run方法中还有需要执行的语句,守护线程也立刻结束运行。我们可以用守护线程做一些不是很严格的工作,线程的随时结束不会产生什么不良的后果。 一个线程调用 void setDaemon(boolean on) 方法可以将自己设置成一个守护(Daemon)线程,线程必须在运行之前设置自己是否是守护线程 .,第10章 输入输出流,10.1 File类 10.2 FileInputStream类 10.3 FileOutputStream类 10.4 FileReader类和FileWriter类 10.5 使用文件对话框打开和保存文件 10.6 RandomAccessFile类,10.7 数据流 10.8 数组流 10.9 对象流 10.10 序列化与对象克隆 10.11 文件锁FileLock 10.12 Process 类中的流 10.13 带进度条的输入流,I/O流,I/O流提供一条通道程序,可以使用这条通道把源中的字节序列送给目的地。把输入流的指向称做源,程序从指向源的输入流中读取源中的数据。而输出流的指向是字节要去的一个目的地(或用户),程序通过向输出流中写入数据把信息传递到目的地。虽然I/O流经常与磁盘文件存取有关,但是程序的源和目的地也可以是键盘、鼠标、内存或显示器窗口。 Java的I/O流库提供大量的流类(在包java.io中)。但是,所有输入流类都是抽象类InputStream(字节输入流)或抽象类Reader(字符输入流)的子类,而所有输出流都是抽象类OutputStream(字节输出流)或抽象类Writer(字符输出流)的子类。,10.1 File类,File类的对象主要用来获取文件本身的一些信息,例如文件所在的目录、文件的长度、文件读写权限等,不涉及对文件的读写操作 构造方法有3个: File(String filename); File(String directoryPath,String filename); File(File f, String filename);,10.2 FileInputStream类,使用文件输入流构造方法建立通往文件的输入流时,可能会出现错误(也被称为异常)。为了把一个文件输入流对象与一个文件关联起来,使用类似于下面所示的代码: try FileInputStream ins = new FileInputStream(“myfile.dat“); catch (IOException e ) System.out.println(“File read error: “ +e ); /文件I/O错误 ,从输入流中读取字节,read方法给程序提供一个从输入流中读取数据的基本方法 , read方法从输入流中顺序读取源中的单个字节数据,该方法返回字节值(0255之间的一个整数),如果到达源的末尾,该方法返回-1。 read方法还有其它一些形式。这些形式能使程序把多个字节读到一个字节数组中: int read(byte b); int read(byte b, int off, int len);,10.3 FileOutputStream类,FileOutputStream提供了基本的文件写入能力。构造方法: FileOutputStream(String name) FileOutputStream(File file) FileOutputStream流使用write方法把字节写入到输出流达到目的地,write的格式如下: public void write(byte b) 其功能是写b.length个字节到输出流。 public void.write(byte b,int off,int len) 其功能是从给定字节数组中起始于偏移量off处写len个字节到输出流。,10.4 FileReader类和FileWriter类,与FileInputStream、FileOutputStream字节流相对应的是FileReader、FileWriter字符流,他们分别是Reader和Writer的子类,其构造方法分别是: FileReader(String filename), FileWriter (String filename)。 由于汉字在文件中占用2个字节,如果使用字节流,读取不当会出现乱码现象,采用字符流就可以避免这个现象,因为,在Unicode字符中,一个汉字被看作一个字符。,10.5 使用文件对话框打开和保存文件,使用文件对话框方便地打开和保存文件,因为文件对话框可以使用户很方便的选择文件所在的目录以及文件的名字。,10.6 RandomAccessFile类,RandomAccessFile类既不是输入流类InputStream类的子类,也不是输出流类OutputStram类的子类流。RandomAccessFile类创建的流的指向既可以作为源也可以作为目的地,换句话说,当我们想对一个文件进行读写操作时,我们可以创建一个指向该文件的RandomAccessFile流即可,这样我们既可以从这个流中读取文件的数据,也可以通过这个流写入数据到文件 . 构造方法。 (1)RandomAccessFile(String name,String mode) 参数name 用来确定一个文件名,给出流的源,同时也是流目的地。参数mode取r(只读)或rw(可读写)决定流对文件的访问权限。 (2)RandomAccessFile(File file,String mode) 参数file 是一个File对象,给出流的源,同时也是流目的地。参数mode取r(只读)或rw(可读写)决定流对文件的访问权限。,10.7 数据流,DataInputStream 类和DataOutputStream类创建的对象被称为数据输入流和数据输出流。这两个流是很有用的两个流,它们允许程序按着机器无关的风格读取Java原始数据。也就是说,当我们读取一个数值时,不必再关心这个数值应当是多少个字节。 构造方法 (1)DataInputStream(InputStream in) 将创建的数据输入流指向一个由参数in指定的输入流,以便从后者读取数据(按着机器无关的风格读取)。 (2)DataOutputStream(OutnputStream out) 将创建的数据输出流指向一个由参数out指定的输出流,然后通过这个数据输出流把Java数据类型的数据写到输出流out。,10.8 数组流,流的源和目标除了可以是文件外,还可以是计算机内存。字节输入流:ByteArrayInputStream 和字节输出流:ByteArrayOutputStream分别使用字节数组作为流的源和目标。使用下列ByteArrayInputStream流的两个构造方法构造字节数组输入流对象: ByteArrayInputStream(byte buf) ByteArrayInputStream(byte buf,int offset,int length),10.9 对象流,ObjectInputStream类和ObjectOutputStream类创建的对象被称为对象输入流和对象输出流。对象输出流使用writeObject(Object obj)方法将一个对象obj写入输出流送往目的地,对象输入流使用readObject()从源中读取一个对象到程序中。构造方法分别是: ObjectInputStream(InputStream in), ObjectOutputStream(OutputStream out)。,10.10 序列化与对象克隆,有时我们想得到对象的一个“复制品”,该复制品的实体是原对象实体的拷贝。复制品实体的变化不会引起原对象实体发生变化,这样的复制品称为原对象的克隆对象或简称克隆。 使用对象流很容易得获取一个序列化对象的克隆。我们只需将该对象写入到对象输出流,那么用对象输入流读回的对象一定是原对象的一个克隆。 一个类如果实现了Serializable接口,那么这个类创建的对象就是所谓序列化的对象。Serializable接口中的方法对程序是不可见的,因此实现该接口的类不需要实现额外的方法,当把一个序列化的对象写入到对象输出流时,JVM就会实现Serializable接口中的方法,将一定格式的文本对象的序列化信息,写入到目的地。,10.11 文件锁FileLock,JDK1.4增加了一个FileLock类,该类的对象称做文件锁。 RondomAccessFil

温馨提示

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

评论

0/150

提交评论