zoukankan      html  css  js  c++  java
  • Java知识点滴(七)

    第7章   Java的高级特性

    137、(P469) Java的异常处理机制:Java建立了一个异常处理机制,能捕获运行期间所发生的错误并抛出一个异常信息,还能按照错误的类别进行处理,这是靠java.lang核心程序包内定义的许多异常对象类来实现的。这种机制可以简化出错代码的结构,把实现具体操作的代码和专门实施出错处理的代码分隔开来。

    138、(P473) 关键字throw和throws:throw语句是产生并抛出一个异常的语句;关键字throws放在方法头后面,说明该方法全部可能发生的异常类型。

    139、(p475 --- p477) 异常的种类和异常类的类层次结构:
             所有异常和错误类型的顶级类Throwable,它是java.lang.Object类的直接子类,且是Serializable接口的实现类。 Throwable类有3个重要的子类,即Error、Exception和RuntimeException类。   其中, Error类和Exception类都是Throwable类的直接子类,而RuntimeException类是Exception类的直接子类。       通常使用Throwable的这三个子类来描述任何实际发生的异常。其用途归纳如下:
             (a)Error类:表示的是无法恢复的错误,例如运行期间发生内存溢出。
             (b)Exception类:与其子类一起表示应捕获异常的合理应用条件。
             (c)RuntimeException类:表示程序设计和实现时所存在的隐患问题在运行期间所产生的异常。如果程序执行正确是决不会发生这种异常的。

    140、(P480) 编写异常处理代码应注意的问题:
                (a)不要把每条语句都封装到一个单独的try语句中,而应该采用划分保护区的办法,把需要保护的一个程序片断作为整体封装到try块中。
                (b)只有在有可能发生异常时才使用try和catch语句,因为捕获异常需要耗费很多执行时间。
                (c)在当前的环境中竟可能解决问题,并将相同的或不同的异常抛出到一个级别更高的环境中。因为那里具有功能更强大的方法函数,可向用户通告错误或放弃一些不成功的命令。
                (d)异常处理应使编程者的类库和程序更加安全健壮,但如果使实际的解决方案变得非常复杂,则只能在确保安全的前提下简化代码。


    141、(P481) 多线程机制:它是Java的一项高级特性,它允许计算机利用程序能同时完成多个任务。为了合理地把CPU分配给所有的任务让它们齐头并进地进行处理,人们提出了“多任务”的概念,但实际上CPU在某一段时间内还是只能执行一个任务,其传统的做法是由CPU的分时机制来实现多任务的同时完成,这是把CPU运行时间分成许多很小的时间段,称为“CPU时间片”,在将CPU时间片分配给各项任务。    Java采用抢占式调度模式来解决线程间的切换问题,因此,没有必要使用时间片。

    142、(P481 --- P483) 进程和线程:
             进程process是程序运行时为完成某项任务所进行的一次执行活动,是程序执行时一个独立运行的基本单位,操作系统必须要为它分配内存资源并占用CPU的执行时间。一个进程所拥有的内存容量很大,在32位微型计算机中最高可达2GB左右。
             在多线程程序中,进程被进一步细分为许多更小的运行单位,即把进程要完成的任务划分成一个个更小的子任务,用细分的许多线程分别去执行。换句话说,在同一个时间片时刻内一个进程可拥有诸多线程,这所有线程都共享着分配给该进程的内存和资源。
             一个线程包含3个主要部分,第1部分是该线程的虚拟CPU, 第2部分是虚拟CPU所执行的程序代码, 第3部分是代码运行时所要处理的数据。   注意:(a) 一个线程既可以执行相同的程序代码,也可以执行不同的程序代码,甚至执行另一个线程的程序代码;
                   (b) 一个线程既可以访问相同的数据,也可以访问不同的数据,甚至访问从另一个线程所得到的相同数据和不同数据。
             多线程技术是将传统的进程进一步细分成多个同时运行的线程,它们共享CPU、内存和数据等资源,线程的划分比进程小,支持多线程的系统要比支持多进程的系统并发度高。与进程相比,生成一个新线程和切换线程的开销要小得多。

    143、(P483 --- P484) 在Java中只需利用Thread类就能方便地生成一个新线程,Thread类是Java继承树根java.lang.Object类的直接子类,且还是Runnable接口的实现类。Runnable接口声明了惟一一个run()方法,凡是预定由一个线程执行的对象,其所属类必定是Runnable接口的实现类,该类必须定义一个无参数的run()方法。
          编程者创建一个新线程并让某个类运行在新线程中,可以有如下两种编程方法:
          (a)将该类定义成Thread类的直接子类。
          (b)利用Runnable接口创建新线程:先定义一个Runnable接口的实现类,然后创建一个Thread类的对象,即创建了一个新线程,并用构造方法的第一个参数Runnable接口的引用target,接收Runnable接口实现类的对象。

    144、(P489) 线程的状态和行为
         任何线程总是处于新建(new thread)、可运行(runnable)、闭锁(blocked)和终止(dead)等4种状态之一,且任何线程从创建到终止都会不断地由一种状态变成另一种状态。这就表现出线程状态的转换和线程之间相互切换的行为。正在运行程序中的每个线程都应具有获取CPU使用权的机会,任何线程都不可能永久独占CPU。
         (a) 新建状态。当用new运算符创建一个Thread类或其子类的对象时,也就创建了一个新线程,该线程就处于新建状态。    处于新建状态的线程不会立即启动,只有等待调用start()方法后才能开始运行。
         (b) 可运行状态。线程一旦调用了start()方法,它就处于可运行状态,而处于可运行状态的线程并不一定在运行,因此称为“可运行状态”,而不是“运行状态”。是否能运行还取决于Java运行环境是否把CPU使用权让给它。只有获得了CPU使用权,线程才能执行自己的代码。
         (c) 闭锁状态。   当发生如下任何一种情况时,一个正在执行的线程进入闭锁状态。
                        c.1)  调用sleep()方法令线程进入睡眠状态。
                        c.2)  因I/O操作未完成使执行受阻。
                        c.3)  线程调用从Thread的父类Object继承的wait()方法,令线程进入等待状态。
                        c.4)  在同步控制时,被另外一个线程锁住。
         (d)终止状态。当前线程的run()方法执行完正常退出后,该线程将自然死亡进入终止状态。可调用Thread类的isActive()方法以判断一个线程是否处于“活跃”状态,即非终止状态。    注意:老版本中用stop()方法异常终止线程,现在已不推荐使用,因为stop()方法是一个不安全的方法函数。
         (e)离开闭锁状态:如下几种情况可以使处于闭锁状态的线程进入到可运行状态。
                        e.1)  当睡眠了指定的毫秒数,即sleep()方法执行完后。
                        e.2)  调用wait()方法而进入等待状态的线程,只有当另一个线程调用notify()方法或notifyAll()方法时,才被唤醒。                     e.3)  因I/O操作未完成而执行受阻的线程,在I/O操作完成后即离开闭锁状态。
                        e.4)  在同步控制时,当拥有“对象锁”的线程放弃它,且被锁的线程获得它。
            注意:老版本的suspend()和resume()方法也与stop()方法一样,现已不推荐使用。

    145、(P491) 抢占式调度模式
        对于多个处于可运行状态的线程,实际上只能选取一个线程运行,该线程一直运行到有一个优先级更高的线程进入到可运行状态,或者正在运行的线程因某种原因被闭锁为止。
        为了确保每个处于可运行状态的线程都有机会获得CPU,编程者应在一段时间内有意地使正在运行的线程暂停一下,以便让其他线程能获得CPU的使用权,或者主动询问正在运行的线程的状态,它可能正在等待外部设备如磁盘机、打印机的操作等。
        有几种办法可暂停正在运行的线程,例如Thread类的静态方法sleep()或yield(),yield()方法是给相同优先级的线程一个执行机会,而sleep()方法是给较低优先级的线程一个执行机会。

    146、(P491) 执行线程实际上就是执行run()方法。线程从执行run()方法开始,当run()方法执行完成后线程也就结束了。
       
    147、(P492) 一个线程可以执行它自身的run()方法,也可以执行一些其他对象的run()方法。

    148、(P492) 在Java中每个线程都具有一个优先级的属性,用1 - 10的整数指定10级优先级别,编程者可以调用setPriority()方法和getPriority()方法设置和获取一个线程的优先级。  在默认情况下,即在编程者没有指定优先级的情况下,一个线程就执行它父类的优先级。       Java虚拟机会自动地把线程优先级映射成主机平台的优先级。

    149、(P492 - P493) 当同一时刻有多个处于可运行状态的线程供选择时,线程调度程序按如下规则选取:
         (a) 总是选取优先级最高的可运行线程投入运行。
         (b) 不断地询问线程状态并唤醒被闭锁的线程,一旦有一个线程从闭锁状态变成可运行状态,重新计算所有可运行线程的优先级,选择优先级最高的线程投入运行。
         可见,线程调度程序不可能平等对待所有线程,它实际上使优先级越高的线程执行时间越多。编程者应在编程时用yield()方法函数给具有相同优先级的线程一个执行机会,用sleep()方法给优先级较低的线程一个执行机会。

    150、(P498) 线程组:对若干个线程,按它们的功能进行归纳分类,这在编程时特别方便,特别是能同时终止一组线程。java.lang.ThreadGroup类就提供此功能,它是Object类的直接子类。

    151、(P499) 同步控制:在多线程程序中,常常会遇到两个或两个以上的线程需要共享同一个对象或数据,这就产生了同步控制问题。
         同步(synchronous):当程序调用一个方法函数时,一直等到方法函数执行完后,才继续执行下一条语句,这就是同步。
         异步(asynchronous):把一条消息发送给一个方法函数后,不管对方执行情况如何就立即执行下一条语句。

    152、(P501) 在线程切换时必须是在一个线程执行完所有部分后再进行。Java提供了很好的同步机制保护数据在线程切换时不被破坏。

    153、(P501) 对象锁标志:在Java中任何类的所有对象都具有一个“对象锁标志”。使用关键字synchronized就可以对这个标志施加影响,即用它设置一个以该关键字开头随后用一对大括号包围的同步块语句。例如,
         public void push(int x)
         {
            synchronized(this)
            {
               data[top] = x;
               top++;
            }
         }
         当一个线程如ta执行到同步块语句时,它便从同步块语句参数所指的对象中取出对象锁标志,这样,线程ta就能够进入到同步块语句的保护区,执行其内的程序代码。如果此时线程tb也去访问此同步块语句,由于对象锁标志已被线程ta取走,它拿不到对象锁标志而无法进入保护区,一直要等到线程ta执行完整个保护区的代码后,把对象锁标志归还,其他对象才有可能拿到对象锁标志而进入代码块。

    154、(P502) 一个线程等待对象锁标志而不能进入同步块语句的保护区,直到取走它的线程归还为止。实际上对象锁标志是在它拿到它的线程执行完保护区内所有代码后自动归还。如果同步块语句发生异常或因break语句打断循环而退出同步块语句,该对象锁标志也能被自动归还。

    155、(P503) 当要将整个方法体作为保护区设置一个同步块语句,且this引用就是要传递给该同步块语句的参数时,把关键字synchronized写在方法函数头作为该方法函数的第2修饰符,如下所示:
         public synchronized void push(int x)
         {
            data[top] = x;
            top++;
         }
         此代码与第153条的代码是完全一致的
    换言之, 用关键字synchronized修饰的方法函数,其保护区是整个方法体,且将this引用作为隐含参数自动地传递给该方法体。

    156、(P503、 P508) 线程间的交互控制:
         实际问题并非都可以划分成相互独立的小任务,因为一项任务的完成会涉及到其他任务的完成情况,这就是说,几个线程之间会发生交互作用。
         现在以两个线程的交互控制来说明线程间交互控制的编程步骤:
         (a) 定义一个类,其对象是两个线程的共享资源。如书中的UStack类,在类体内不仅要编写完成任务的方法如push()和top()方法,还要编写调用wait()、notify()或notifyAll()等方法的语句。这样实现基于共享对象的线程间通讯机制。
         (b) 定义两个Runnable接口的实现类,并用构造方法的参数把共享对象传递给这两个类。
         (c) 创建两个线程(即Thread类的对象), 并将第2步中两个类的对象通过构造方法分别传给两个线程。
         (d) 调用start()方法分别启动这两个线程。

    157、(P508) 死锁问题(deadlock)
        在采用同步机制的多线程程序中,若几个线程共享两个以上的对象和资源将可能发生“死锁”问题。例如,一个线程正在等待另一个线程所取走的对象锁标志,与此同时,这另一个线程又在等待前一个线程所掌握的对象锁标志,在这一种情况下,那个线程都不能向前推进到同步块语句的最末端。   
        Java没有提供避开和解决死锁问题的通用方法,只是从JDK1.2版本开始反对使用Thread类的stop()、resume()、suspend()、destroy()等方法,以减少死锁问题的发生。

    158、(P509) Java是面向Internet的编程语言,它的输入/输出流库比C++要复杂得多。首先,要考虑3种不同种类的输入/输出,即文件、控制台和网络,还需要考虑用不同的方式,如顺序访问、随机访问、二进制、字符、按行、按字节等诸多方式。
                Java输入/输出流库引入了缓冲器机制进行逻辑抽象,使得读取和写入网络服务器的数据与读取和写入一个磁盘文件或设备文件没什么区别。
                输入/输出流库被封装在java.io包中。

    159、(P509) 流的工作原理:在网络上要经常实现各种不同形式的输入/输出操作,如文件的读写、控制台的输入输出以及网络间的数据传输等。Java流库把它们都抽象成“流操作”,简称为“流”(stream),流以字节为单位传送数据。       流的源点是一个与流相关的字节集合,因此,各种不同形式的数据在这里都必须转换成由一个个字节组成的字节集合才能传输。

    160、(P509) 输入输出是针对计算机而言的。输入流只能做读取操作而不能做写入操作,输出流只能进行写入操作而不能做读取操作。
                输入流是数据的“源”,数据由它读取而来,读取操作也是一次读一个字节,然后经过过滤器处理获得用户所需要的数据。FilterInputStream类就具有这样的过滤器转换功能。     一个输入流“结点”可能是来自磁盘文件、键盘或内存区。
                输出流是数据的拷贝,它只能进行写入操作。   输入流的顶级类InputStream和输出流的顶级类OutputStream都是抽象类,其派生类具有各种不同的功能,详情参见Java API。

    161、(P514) BufferedInputStream和BufferedOutputStreame, 它们是缓冲器的输入流和输出流, 它们在内存中为流建立了一个缓冲器,以减少对磁盘的读写操作来加快程序的执行速度。

    162、(P515) 除了从控制台的键盘接收数据和向屏幕显示数据的输入输出操作外,文件的读写操作就是最常用的输入输出操作了。Java流库提供了File、FileInputStream、FileOutputStream、RandomAccessFile等类来处理文件。 其中,FileInputStream类和FileOutputStream类分别是抽象类InputStream和OutputStream的直接子类,用于从文件读写字节数据,也可以与各种过滤器流类协作以获得所需要的功能。File类用来描述文件的所有信息。 (P524) RandomAccessFile类是一个功能更强、更便于处理磁盘文件的流类,几乎可以从各种类型的文件中随心所欲地读写任何类型的数据,不管它是二进制文件还是文本文件,也不管是读写部分文件还是整个文件。

    163、(P526) Java采用Unicode代码对字符进行编码,但标准流库中的流实际上是以字节为单位进行操作,这就产生了字节和Unicode字符间的互相转换问题。为此,Java提供了一个标准的转换机制,即在java.io程序包内定义了两个抽象类Reader和Writer。这两个类能自动地完成字节与Unicode字符间的互相转换。抽象类Reader的子类InputStreamReader是把字节流转换成字符流的桥梁,而抽象类Writer的子类OutputStreamWriter是把特定编码的字符流转换成字节流的桥梁。        为了提高执行效率,通常把InputStreamReader与另一个特殊输入流BufferedReader链接在一起使用,如:BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    同样,通常把OutputStreamWriter和BufferedWriter链接在一起使用,如:BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));

    164、(P527) 对象系列化:在java.io包内还提供了一个Serializable接口,它能够使Java虚拟机具有把一个对象存放在流中以便从一个地方传送到另一个地方,其传送的范围不仅在主机内,而且可以在计算机网络乃至整个Internet。     Serializable接口实际上没有声明任何方法函数,它只是给某个类的对象附上一个标记,以表示该类是Serializable接口的一个实现类。     不是Serializable接口的实现类对象不能被系列化。
         对象系列化的思想是:如果能够把对象的主要信息转化为一个系列化的字节数据,那么,它们就可以方便地存储在流类的对象中,也就可以在网络上从一个源主机到目标主机上,并在目标主机上恢复成员来的对象。这就是对象的存储和恢复机制。

    165、(P533) Java的一大高级特性是支持多媒体,它不仅能链接静态图片和图像,而且还能实现动画的显示和声音的播放,能方便地融入图形、图像、声音和录像甚至电影等多媒体信息。Java多媒体框架将高级媒体格式如视频和音频集成到Java API,能支持处理所有媒体类型。
         (P533) 在java.awt程序包中提供了一个抽象类Image,它是Object类的直接扩展,是描述图像所有类的超类。
         (P534) 图像产生器(ImageProducer)负责生成图像位图并把它们传递给所有被注册的图像消费器(ImageConsumer)。通过各种不同的图像过滤器ImageFilter类处理可以实现图像的剪裁、放大或缩小、色调的变换等功能。
         (P536、P537) 在java.awt.image程序包中还定义了一个ImageObserver接口。该接口实现类的对象就是一个图像观察器,可以监视图像产生器的图像生产过程。所有组件(不管是AWT组件还是Swing组件),都可以作为图像观察器。因为Component类就是ImageObserver的实现类。

    166、(P537) 双缓冲技术:在显示多帧图像时会产生画面闪动的现象,这是因为显示新的一帧必须擦掉前一帧画面,然后再显示新的一帧。双缓冲技术是指,图像不直接在组件中绘制和清除,另外在添加一个屏幕外的缓冲区,让所有的绘制和清除工作在该缓冲区中完成。当图像需要切换时,下一帧图像已经在缓冲区中绘制完成,可以立即复制到图像组件,从而减少了执行时间而消除了闪烁。

    167、(P537) 在应用程序中加载和显示图像:应用程序必须通过抽象类Toolkit声明的抽象方法getImage()来加载图像。
                       public abstract Image getImage(String filename)
         该方法由参数filename指定的GIF、JPEG和PNG等格式的文件中获取位图数据,并返回一个位图数据所描述的图像对象。

    168、(P543) 对于应用程序装载声音文件,java.applet.Applet类提供了如下一个静态方法
                       public static final AudioClip newAudioClip(URL url)
         可用该方法来装载声音文件,它们都返回一个AudioClip接口的引用变量指向所装载的声音文件,这样可以调用定义于AudioClip接口内的play()和loop()方法播放声音文件。                   

                   
     


     

  • 相关阅读:
    勿忘初心
    欧拉函数与数论的结合UVA11426
    法雷级数
    欧拉函数及其应用
    poyla计数问题
    组合计数问题中容斥原理的应用
    数学问题当中的一些基本计数问题
    HDU4642博弈好题
    KMP算法在字符串中的应用
    UVA11722概率问题之线性规划
  • 原文地址:https://www.cnblogs.com/it_han_ku/p/481903.html
Copyright © 2011-2022 走看看