黑马程序员--Java学习15--异常与多线程
2014-05-29 18:19
459 查看
---------------------- ASP.Net+Unity开发、.Net培训、期待与您交流!
----------------------
一、异常
1、异常概念
异常是对问题的描述,将问题进行对象的封装。
异常的体系如下:
这只是一部分,也是我们要重点学习的。
异常体系的特点:异常体系中的所有类以及建立的对象都是具备可抛性,也就是说可以被throw和throws关键字所操作。也只有异常体系具备这个特点
2、throw和throws的用法
throw 定义在函数内,用于抛出异常对象。
throws定义在函数上,用于抛出异常类,可以抛出多个,用逗号隔开
当函数内容有throw抛出异常对象,并未进行try 处理。必须在函数上进行声明。否则编译失败
注意:RuntimeException除外,也就是说,函数内如果抛出RuntimeException异常,函数上不用声明
如果,函数声明了异常,调用者需要进行处理,处理方法可以throws 也可以 try catch.
异常有两种:
编译时被检测异常
该异常在编译时,如果没有处理(没有抛也没有try),编译失败
该异常被标识,代表这可以被处理。
运行时异常(编译时不检测)
在编译时,不需要处理,编译器不检查。
该异常的发生,建议不处理,让程序停止,需要对代码进行修正(RuntimeException类及其子类)
一个简单的除法运算的例子来看看throw和throws是怎么用的:
运行结果是:0;
但是当我们这样做呢:double c=div(3,0);
结果如下:
ArithmeticException:当出现异常的运算条件时,抛出此异常。例如,一个整数“除以零”时,抛出此类的一个实例
对于这样的代码,我们知道他会出现异常,那么如何解决呢,我们来看看将异常抛出:
这时的结果是:
3、异常处理的语句 try catch
try-catch 语句是对异常进行处理的语句。其格式有三种:
try中放的是要执行的代码,catch是对捕捉到的遗产进行的处理
运行结果是:
但是要注意的是:注意:1、finally中定义的通常是 关闭资源代码,因为资源必须释放。2、finally 只有一种情况不会执行,当执行到System.out.exit(0);finally不会再执行
4、自定义异常
自定义异常: 定义类继承Exception或者RuntimeException 1、为了让该自定义类具备可抛性 2、让该类具备操作异常的共性方法
当要定义自定义异常的信息时,可以使用父类已经定义好的功能将异常信息传递给构造函数
5、异常在子父类覆盖中的体现
异常在子父类覆盖中需要注意的:
1、子类在覆盖父类时,如果父类的方法抛出异常,那么子类的覆盖方法,只能抛出父类的异常或者该异常的子类。
2、如果父类方法抛出多个异常,那么子类在覆盖该方法时,只能抛出父类异常的子集。原则是父类能处理。
3、如果父类或者接口的方法中没有异常抛出,那么子类在覆盖方法时,也不可以抛出异常。
如果子类方法发生了异常,就必须要进行try处理,绝对不能抛出。
二、多线程
1、多线程的概念
以往开发的程序大多是单线程的,即一个程序只有一条从头至尾的执行线索。然而现实世界中的很多过程都具有多条线索同时动作的特性:例如,我们可以一边看电视,一边活动胳膊,如果不容许这样做,我们会感觉很难受。再如一个网络服务器可能需要同时处理多个客户机的请求等。
Java的一大特性点就是内置对多线程的支持。多线程是指同时存在几个执行体,按几条不同的执行线索共同工作的情况,它使得编程人员可以很方便地开发出具有多线程功能,能同时处理多个任务的功能强大的应用程序。虽然执行线程给人一种几个事件同时发生的感觉,但这只是一种错觉,因为计算机在任何给定的时刻只能执行那些线程中的一个。为了建立这些线程正在同步执行的感觉,Java快速地把控制从一个线程切换到另一个线程。
2、线程创建的两种方式:继承Thread类和使用Runnable接口
创建线程的第一种方式:继承Thread类
步骤:
1、定义类继承Thread类
2、复写Thread类中的run方法
目的:将自定义的代码存储在run方法,让线程运行
3、调用线程的start方法,该方法有两个作用:1、启动线程 2、调用方法
运行结果是:
可以看出不同的线程在同时运行着。
创建线程的第二种方式:实现Runnable接口
步骤:
1、定义实现Runnable接口
2、覆盖Runnable接口中的run方法。
3、通过Thread类建立线程对象。
4、将Thread接口的子类对象作为实际参数传递给Thread类的构造函数。
5、调用Thread类的start方法开启线程并调用Runable接口子类的run方法。
运行结果也是几个线程同时运行,顺序不定。
那么实现方式和继承方式有什么不同呢?
实现方式:避免了单继承的局限性,在定义线程时,
建议使用实现方式
两种方式的区别:
继承Thread:线程大妈存放在Thread子类run方法中。
实现Runnable:代码存放在接口的子类的run方法。
3、多线程中的安全问题
问题的原因:当多条语句在操作同一线程共享数据时,一个线程对多条语句只执行了一部分还没有执行完,另一个线程参与进来,导致共享数据的错误解决办法:对多条操作共享数据的语句只能让一个线程都执行完,在执行过程,其他线程不可以参与执行
Java对于多线程问题提供了专业的解决办法
就是同步代码
同步的前提:
1、必须要有两个或者两个以上的线程
2、必须是多个线程使用同一个锁
必须保证同步中只能有一个线程运行
好处:解决了多线程的安全问题。
弊端:多个线程需要先判断锁,较为消耗资源
4、懒汉式
在单例设计模式中我提到了,饿汉式和懒汉式,那么多线程中的懒汉式为:
这种方式提高了效率,保证了对象的唯一。
---------------------- ASP.Net+Unity开发、.Net培训、期待与您交流!
----------------------
----------------------
一、异常
1、异常概念
异常是对问题的描述,将问题进行对象的封装。
异常的体系如下:
<span style="font-size:14px;"><span style="font-size:14px;">Throwable |--Error |--Exception |--RuntimeExceptio </span></span>
这只是一部分,也是我们要重点学习的。
异常体系的特点:异常体系中的所有类以及建立的对象都是具备可抛性,也就是说可以被throw和throws关键字所操作。也只有异常体系具备这个特点
2、throw和throws的用法
throw 定义在函数内,用于抛出异常对象。
throws定义在函数上,用于抛出异常类,可以抛出多个,用逗号隔开
当函数内容有throw抛出异常对象,并未进行try 处理。必须在函数上进行声明。否则编译失败
注意:RuntimeException除外,也就是说,函数内如果抛出RuntimeException异常,函数上不用声明
如果,函数声明了异常,调用者需要进行处理,处理方法可以throws 也可以 try catch.
异常有两种:
编译时被检测异常
该异常在编译时,如果没有处理(没有抛也没有try),编译失败
该异常被标识,代表这可以被处理。
运行时异常(编译时不检测)
在编译时,不需要处理,编译器不检查。
该异常的发生,建议不处理,让程序停止,需要对代码进行修正(RuntimeException类及其子类)
一个简单的除法运算的例子来看看throw和throws是怎么用的:
<span style="font-size:14px;"><span style="font-size:14px;">class Test { public static void main(String[] args) { int c=div(3,6); System.out.println(c); } //定义一个除法运算 public static int div(int a,int b) { return a/b; } }</span></span>
运行结果是:0;
但是当我们这样做呢:double c=div(3,0);
结果如下:
ArithmeticException:当出现异常的运算条件时,抛出此异常。例如,一个整数“除以零”时,抛出此类的一个实例
对于这样的代码,我们知道他会出现异常,那么如何解决呢,我们来看看将异常抛出:
<span style="font-size:14px;">class Test { public static void main(String[] args) { int c=div(3,0); System.out.println(c); } //定义一个除法运算 public static int div(int a,int b) throws ArithmeticException{ if (b==0) { throw new ArithmeticException("除零了");//此处抛出了异常 } return a/b; } }</span>
这时的结果是:
3、异常处理的语句 try catch
try-catch 语句是对异常进行处理的语句。其格式有三种:
<span style="font-size:14px;">第一种 try { } catch () { } 第二种 try { } finally { } 第三种 try { } catch () { } finally{ }</span>
try中放的是要执行的代码,catch是对捕捉到的遗产进行的处理
<span style="font-size:14px;"><pre class="java" name="code">class Test { public static void main(String[] args) { try { int c=div(3,0); System.out.println(c); } catch (ArithmeticException e) { System.out.println("分母为零,无法进行运算"); } finally { System.out.println("finally中的代码是一定运行的"); } } //定义一个除法运算 public static int div(int a,int b) throws ArithmeticException{ if (b==0) { throw new ArithmeticException();//此处抛出了异常 } return a/b; } }</span>
运行结果是:
但是要注意的是:注意:1、finally中定义的通常是 关闭资源代码,因为资源必须释放。2、finally 只有一种情况不会执行,当执行到System.out.exit(0);finally不会再执行
4、自定义异常
自定义异常: 定义类继承Exception或者RuntimeException 1、为了让该自定义类具备可抛性 2、让该类具备操作异常的共性方法
当要定义自定义异常的信息时,可以使用父类已经定义好的功能将异常信息传递给构造函数
<span style="font-size:14px;">/* 有一个圆形和长方形。 都可以获取面积。对于面积如果出现非法的数值,视为是获取面积出现问题。 问题通过异常来表示。 现有对这个程序进行基本设计。 */ class NoValueException extends Exception { NoValueException(String message) { super(message); } } interface Shape { void getArea(); } class Rec implements Shape { private int len,wid; Rec(int len,int wid)throws NoValueException { if (len<=0||wid<=0) { throw new NoValueException("数据传入有误!1"); } else { this.len = len; this.wid = wid; } } public void getArea() { System.out.println(len*wid); } } class Circle implements Shape { private int radius; public static final double PI = 3.14; Circle(int radius)throws NoValueException { if (radius<=0) { throw new NoValueException("数据传入有误!2"); } this.radius = radius; } public void getArea() { System.out.println(radius*radius*PI); } } class ExceptionTest1 { public static void main(String[] args) { try { Circle c =new Circle(-3); c.getArea(); Rec r = new Rec(-3,1); r.getArea(); } catch (NoValueException e) { System.out.println(e.toString()); } } }</span>
5、异常在子父类覆盖中的体现
异常在子父类覆盖中需要注意的:
1、子类在覆盖父类时,如果父类的方法抛出异常,那么子类的覆盖方法,只能抛出父类的异常或者该异常的子类。
2、如果父类方法抛出多个异常,那么子类在覆盖该方法时,只能抛出父类异常的子集。原则是父类能处理。
3、如果父类或者接口的方法中没有异常抛出,那么子类在覆盖方法时,也不可以抛出异常。
如果子类方法发生了异常,就必须要进行try处理,绝对不能抛出。
<span style="font-size:14px;">class AException extends Exception { } class BException extends AException { } class CException extends Exception { } class Fu { void show()throws AException { } } class Zi extends Fu { void show()//要么不抛,要么throws AException,要么throws BException,不能throws CException。 { //如果子类内部真的发生了CException,只能内部处理,不能抛。 } } class Test { void function(Fu f) { try { f.show(); } catch (AException e) { } } } class CatchDemo2 { public static void main(String[] args) { Test t = new Test(); t.function(new Zi()); } }</span>
二、多线程
1、多线程的概念
以往开发的程序大多是单线程的,即一个程序只有一条从头至尾的执行线索。然而现实世界中的很多过程都具有多条线索同时动作的特性:例如,我们可以一边看电视,一边活动胳膊,如果不容许这样做,我们会感觉很难受。再如一个网络服务器可能需要同时处理多个客户机的请求等。
Java的一大特性点就是内置对多线程的支持。多线程是指同时存在几个执行体,按几条不同的执行线索共同工作的情况,它使得编程人员可以很方便地开发出具有多线程功能,能同时处理多个任务的功能强大的应用程序。虽然执行线程给人一种几个事件同时发生的感觉,但这只是一种错觉,因为计算机在任何给定的时刻只能执行那些线程中的一个。为了建立这些线程正在同步执行的感觉,Java快速地把控制从一个线程切换到另一个线程。
2、线程创建的两种方式:继承Thread类和使用Runnable接口
创建线程的第一种方式:继承Thread类
步骤:
1、定义类继承Thread类
2、复写Thread类中的run方法
目的:将自定义的代码存储在run方法,让线程运行
3、调用线程的start方法,该方法有两个作用:1、启动线程 2、调用方法
/* 需求:简单的卖票程序。 多个窗口同时买票。 */ class Ticket extends Thread { private static int ticket=100; public void run() { while(ticket>0) { System.out.println(Thread.currentThread().getName()+"...ticket"+ticket--); } } } class TicketDemo { public static void main(String[] args) { Ticket t2= new Ticket(); Ticket t3= new Ticket(); Ticket t4= new Ticket(); t2.start(); t3.start(); t4.start(); } }
运行结果是:
可以看出不同的线程在同时运行着。
创建线程的第二种方式:实现Runnable接口
步骤:
1、定义实现Runnable接口
2、覆盖Runnable接口中的run方法。
3、通过Thread类建立线程对象。
4、将Thread接口的子类对象作为实际参数传递给Thread类的构造函数。
5、调用Thread类的start方法开启线程并调用Runable接口子类的run方法。
class Ticket implements Runnable//extends Thread { private /*static */ int ticket=100; public void run() { while(ticket>0) { System.out.println(Thread.currentThread().getName()+"...ticket"+ticket--); } } } class TicketDemo { public static void main(String[] args) { Ticket t= new Ticket(); Thread t1 = new Thread(t); Thread t2 = new Thread(t); Thread t3 = new Thread(t); Thread t4 = new Thread(t); t1.start(); t2.start(); t3.start(); t4.start(); } }
运行结果也是几个线程同时运行,顺序不定。
那么实现方式和继承方式有什么不同呢?
实现方式:避免了单继承的局限性,在定义线程时,
建议使用实现方式
两种方式的区别:
继承Thread:线程大妈存放在Thread子类run方法中。
实现Runnable:代码存放在接口的子类的run方法。
3、多线程中的安全问题
问题的原因:当多条语句在操作同一线程共享数据时,一个线程对多条语句只执行了一部分还没有执行完,另一个线程参与进来,导致共享数据的错误解决办法:对多条操作共享数据的语句只能让一个线程都执行完,在执行过程,其他线程不可以参与执行
Java对于多线程问题提供了专业的解决办法
就是同步代码
synchronized(对象) { 需要同步的代码(谁需要操作共享数据谁就是同步代码) }
同步的前提:
1、必须要有两个或者两个以上的线程
2、必须是多个线程使用同一个锁
必须保证同步中只能有一个线程运行
好处:解决了多线程的安全问题。
弊端:多个线程需要先判断锁,较为消耗资源
class Ticket implements Runnable{ private /*static */ int ticket=1000; Object obj=new Object(); public void run() { synchronized(obj) { while(ticket>0) { try { Thread.sleep(10);} catch(Exception e) { } System.out.println(Thread.currentThread().getName()+"...ticket.."+ticket--); } } } } class TicketDemo3 { public static void main(String[] args) { Ticket t= new Ticket(); Thread t1 = new Thread(t); Thread t2 = new Thread(t); Thread t3 = new Thread(t); Thread t4 = new Thread(t); t1.start(); t2.start(); t3.start(); t4.start(); } }
4、懒汉式
在单例设计模式中我提到了,饿汉式和懒汉式,那么多线程中的懒汉式为:
/* 单利设计模式: 饿汉式 class Single { private static final Single s = new Single(); private Single(){} public static Single getInstance() { return s; } } */ //懒汉式 //效率较低 class Single { private static Single s=null; private Single(){} public static synchronized Single getInstance() { if (s==null) { s=new Single(); } return s; } } //提高效率 class Single { private static Single s=null; private Single(){} public static Single getInstance() { if(s==null){//双重判断 synchronized(Single.class)//锁为:该类所属的字节码文件对象 if (s==null) { s=new Single(); } } } return s; } }
这种方式提高了效率,保证了对象的唯一。
---------------------- ASP.Net+Unity开发、.Net培训、期待与您交流!
----------------------
相关文章推荐
- 黑马程序员Java学习日记(3)异常,String,多线程
- 黑马程序员 (1) 对JAVA多线程编程进行学习。
- 黑马程序员java学习笔记之四(java多线程总结)
- 黑马程序员之JAVA学习笔记:多线程学习大总结
- 黑马程序员java学习—异常
- 黑马程序员 – 学习Java5中的多线程(1) – 2012.10.29
- 黑马程序员_关于java异常机制的学习
- 黑马程序员_Java学习日记第三天-多态、内部类、异常处理
- 黑马程序员_java多线程学习笔记
- 黑马程序员:java学习要点-多线程(上)
- 黑马程序员-java学习之异常
- 黑马程序员---- Java学习笔记:1.异常 2.集合
- 黑马程序员--Java学习日记6_多线程
- 黑马程序员_java多线程学习
- 黑马程序员Java培训、Android培训-Java 学习过程记录_多线程2
- 黑马程序员——Java异常处理学习笔记
- 黑马程序员_Java学习日记15_File
- 黑马程序员-学习日记_JAVA中异常
- 黑马程序员 – 学习Java5中的多线程(2) – 2012.12.30
- 黑马程序员_java学习之异常处理