黑马程序员_04_Java语言(异常,多线程,线程间通信)

-------  android培训、 java培训、期待与您交流! ----------

1. 异常的概念

     1.1什么是异常

          异常指的是程序运行时出现的非正常情况.

     1.2异常的层次

          Java的异常类是处理运行时的特殊类,每一种异常对应一种特定的运行错误.所有Java异常类都是系统类库中Exception类的子类,其继承结构如图:

   wKioL1P8ZorzDrxKAAEdOGcEoJs849.jpg

          Throwable类为该处理层次的最高层,其中定义了一个异常描述串,以及获取该描述的getMessage()方法.

               对于严重的:Error类时JVM系统内部错误,程序中不能对其编程处理.

                 //对Error一般不编写针对性的代码对其进行处理

               对于不严重的:Exception类时程序代码中要处理的异常,这类异常发生可能与程序运行时的数据有关.

                 //可进行相应处理     

   

     1.3系统定义的异常

          Exception类有若干子类,每个子类代表一种特定的运行错误,这些子类有的是系统事先定义好并包含在Java类库中的,成为系统定义的运行异常,如下表:

     wKiom1P8ZZazIVUHAANKqG6Xg_I050.jpg

2. 异常的处理

     2.1 try...catch..finally结构

            ①try 

               {语句块;} 

            ②catch (异常类名   参变量名)      //注意如果没有catch就代表异常没被处理过,如果该异常是检测时异常,则必须声明.

                {语句块;}  

            ③finally     //定义一定执行的代码:通常用于关闭资源

               {语句块;} 

             1,2    1,3,     1,2,3   三种方式都是合法语句.

     (1)一个try可以引导多个catch块。但是不要定义多余的catch块,多个catch块的异常出现继承关系,父类异常catch块放在最后面。

     (2)异常发生后,try块中的剩余语句将不再执行。 

     (3)catch块中的代码要执行的条件是,首先在try块中发生了异常,其次异常的类型与catch要捕捉的一致。 建议声明更为具体的异常,这样处理的可以更具体。

     (4)可以无finally部分,但如果存在,则无论异常发生否,finally部分的语句均要执行。即便是try或catch块中含有退出方法的语句return,也不能阻止finally代码块的执行;除非执行System.exit(0)等导致程序停止运行的语句。 

3. 自定义异常(编译时检测的异常 和 不被检测的异常[RuntimeException以及子类])

     3.1 自定义异常类设计

          创建用户自定义异常一般是通过继承Exception来实现。在自定义异常中,一般包括异常标识,构造方法和toString()方法.

     3.2 抛出异常

          通过throw语句抛出,异常的本质是对象,因为throw关键词后跟的是new运算符来创建的一个异常对象.

     3.3 方法的异常声明

          如果一个方法有异常抛出,有两种选择:

          [1]在方法内对异常进行捕获处理

          [2]在方法内不处理异常,而是交给外部调用程序,这是要在方法头使用throws子句列车该方法可能产生的异常.

     3.4 继承Exception原因:

          异常体系有一个特点:因为异常类和异常对象都可被抛出.他们都具备可抛性,这是Throwable体系中独有特点.只有这个体系中的类和对象才可以被throws和throw操作.

     3.5 异常在子类覆盖中的体现:

          1.子类覆盖父类时,如果父类的方法抛出的异常,那么子类只能抛出父类异常或该异常的子类.

          2.如果父类方法抛出多个异常,那么子类在覆盖方法时,只能抛出父类异常的子集.

          3.如果父类或借口的方法中没有异常抛出,那么子类在覆盖方法时,也不可能抛出异常.如果子类方法发生异常,就必须进行try处理,绝对不能抛.      

4. 线程的概念

     4.1多进程与多线程

          进程:一个正在执行的程序.每个进程执行都有一个执行顺序,该顺序是一个执行路径,或叫一个控制单元.

               多进程的缺点:

进程切换开销大;

进程间的通信很不方便。

          多线程: 指的是在单个程序中可以同时运行多个不同的线程,执行不同的任务,线程切换的开销小 。

     4.2线程的状态

          Java语言使用Thread类及其子类的对象来表示线程,新建的线程在它的一个完整的生命周期通常要经历5种状态.

wKioL1P8Z7agpBPpAACtapy1mAs907.jpg

     4.3线程调度与优先级

     Java采用抢占式调度策略,下面几种情况下,当前线程会放弃CPU: 
          (1)当前时间片用完; 
          (2)线程在执行时调用了yield() 或sleep() 方法主动放弃;  
          (3)进行I/O 访问,等待用户输入,导致线程阻塞;或者为等候一个条件变量,线程调用wait()方法;    
          (4)有高优先级的线程参与调度。 
     线程的优先级用数字来表示,范围从1~10。主线程的默认优先级为5
          Thread.MIN_PRIORITY=1
          Thread.NORM_PRIORITY=5 

          Thread.MAX_PRIORITY=10

5. 多线程编程方法

     5.1 Thread类简介

          Thread类综合了Java程序中一个线程需要拥有的属性和方法,其构造方法如下:

               public Thread (ThreadGroup group,Runnable target,String name);

      

               public Thread();

               public Thread(Runnable target);

               public Thread(Runnable target,String name);

               public Thread(String name);

               public Thread(ThreadGroup group,Runnable target);

               public Thread(ThreadGroup group,String name);  

          Thread类的主要方法以及功能如表

wKioL1P8ZtWyleGJAANdD7K_9YU775.jpg

     5.2 继承Thread类实现多线程     

          需要重写run方法实现线程的任务.需要注意的是,程序中不要直接调用此方法,而是调用线程对象的start()方法启动线程,让其进入可调度状态,线程获得调度自动执行run()方法.    

     5.3 实现Runnable接口编写多线程

          通过 Thread 类的构造函数public Thread(Runnable target)可以将一个Runnable 接口对象传递给线程,线程在调度时将自动调用Runnable 接口对象的run方法。 

6. 线程资源的同步处理

     6.1 临界资源问题

wKioL1P8Z4ayeJJcAACC3rgeySg856.jpg

     Java对于多线程的安全问题提供了专业的解决方式:  就是同步代码块

          synchronized(对象)

               { 需要被同步的代码 }

          对象如同锁,持有锁的线程可以再同步中执行.

          没有持有锁的线程及时获取cpu的执行权,也进不去,因为没有获取锁.

          同步的前提:

               1.必须要有两个或者以上的线程

               2.必须要多个线程使用同一个锁     

          好处:解决了多线程的安全问题

          弊端:多个线程需要判断锁,较为消耗资源.

     

     同步函数用的是哪个锁:

           函数需要被对象调用,那么函数都有一个所属对象的引用.就是this.

          所以同步函数使用的锁是this锁.静态函数使用的是该方法所在类的字节码文件对象.

     6.2 wait()和notify()

     6.3 避免死锁

          多个线程相互等待对方释放持有的锁,并且在得到对方锁之前不释放自己的锁.(自己能写一个死锁代码)   

7. 线程间通信

     思考1: wait(),notify(),nofifyAll()用来操作线程为什么定义在Object类中?

          1.这些方法存在同步中,用来操作同步中的线程,必须要标志它们所操作线程的只有锁.

          2.使用这些方法必须标识出所属同步的锁,只有同一个锁上被等待线程,可以被同一个锁上notify唤醒.不可以对不同锁中的线程进行唤醒.

          3.锁可以是任意对象,所以任意对象调用的方法一定定义Object类中.

     思考2:wait(),sleep()有什么区别?

          wait():释放资源,释放锁

          sleep():释放资源,不释放锁

     

     生产消费者问题

     生产消费者问题--JDK1.5提供的多线程升级解决方法

          将同步synchronized替换成Lock操作.

          将Object中的wait,notify,notifyAll方法替换成Condition对象.

          该对象可以Lock锁进行获取.

     停止线程

          1.定义循环结束标记

               因为线程运行代码一般都是循环,只是控制了循环即可.

          2.使用interrupt(中断)方法: 该方法是结束线程的冻结状态,使线程回到运行状态中来.这样就可以操作标记结束.

          (注)stop方法已过时不在再使用.

          setDeamon()方法

               标记为后台线程, 当所有前台前程结束后会自动结束.     

          join()方法

               等待该线程终止, 其实是抢夺CPU执行权.

               当A线程执行到B线程的.join()方法, A就会等待. 等B线程都执行完, A才会执行. join可以用来临时加入线程执行.

          toString()

               返回该线程的字符串表示形式,包括线程名称,优先级和线程组

          yield()

               暂停当前执行的线程对象,并执行其他线程

你可能感兴趣的:(android,程序员,java培训)