大数据编程入门:Java异常处理
在使用Java编写程序的时候,会出现一些错误,我们通常称之为异常。在我们遇到异常的时候应该怎么去处理呢?今天小编将为大家带来大数据编程入门:Java异常处理这篇文章。
一、异常的分类
在Java程序中所遇到的有三种异常,由用户错误引起的异常、由程序错误引起的异常及由物理错误引起的异常。
由用户错误引起的异常,通常包括:
① 用户输入了非法数据。
② 要打开的文件不存在。
③ 网络通信时连接中断,或者JVM内存溢出。
在我们了解到异常处理是怎么工作前,我们需要掌握以下三种类型的异常:
① 检查性异常: 最具代表性的检查异常是由程序员无法预见的用户错误或问题引起的。例如,要打开一个不存在的文件,会发生一个异常,在编译时不能简单地忽略它。 ② 运行时异常: 运行时异常是程序员可以避免的异常。与检查性异常不同,运行时异常可以在编译时忽略。③ 错误: 错误不是例外,而是程序员无法控制的问题。错误通常在代码中被忽略。例如,当堆栈溢出时,会发生错误,并且在编译期间无法检查它们。
二、Exception类的层次
所有异常类都是从java.lang.Exception继承的子类。
Exception类是Throwable类的子类。除了Exception类之外,Throwable还有一个子类Error。
Java程序通常不会捕获错误。错误通常发生在严重故障的情况下,它们不在Java程序处理的范围之内。
Error用于指示运行时环境中的错误。
例如,JVM内存溢出。通常,程序不会从错误中恢复。
Exception类有两个主要的子类:IOException类和RuntimeException类。
三、Java 内置异常类
Java语言在Java中定义了一些异常类在 java.lang标准包。
标准运行时异常类的子类是最常见的异常类。因为 java.lang包默认加载到所有Java程序中,从运行时异常类继承的大多数异常都可以直接使用。
Java还根据每个类库定义了一些其他异常,下表列出了Java的非检查性异常。
异常
描述
ArithmeticException
当出现异常的运算条件时,会引发此异常。例如,当一个整数被“零除”时,抛出这个类的一个实例。
ArrayIndexOutOfBoundsException
访问具有非法索引的数组时引发异常。如果索引为负数或大于或等于数组大小,则该索引是非法的。
ArrayStoreException
尝试将错误类型的对象存储到对象数组时引发异常。
ClassCastException
当试图将对象强制转换为不是实例的子类时,会引发此异常。
IllegalArgumentException
引发的异常表示传递给方法的参数非法或不正确。
IllegalMonitorStateException
抛出异常以指示线程已尝试等待对象的监视器,或通知正在等待对象监视器但未指定监视器的另一个线程。
IllegalStateException
在非法或不适当的时间调用方法时产生的信号。换句话说,Java环境或Java应用程序没有处于请求操作所需的适当状态。
IllegalThreadStateException
线程未处于请求操作所需的适当状态时引发异常。
IndexOutOfBoundsException
指示排序索引(例如对数组、字符串或向量的排序)超出范围。
NegativeArraySizeException
如果应用程序试图创建大小为负的数组,则抛出该异常。
NullPointerException
当应用程序试图在需要对象的地方使用 null 时,抛出该异常
NumberFormatException
当应用程序尝试将字符串转换为数字类型,但无法将该字符串转换为适当的格式时,会引发此异常。
SecurityException
由安全管理器抛出的异常,指示存在安全侵犯。
StringIndexOutOfBoundsException
此异常由 String 方法抛出,指示索引或者为负,或者超出字符串的大小。
UnsupportedOperationException
当不支持请求的操作时,抛出该异常。
下表列出了Java定义在java.lang包中的检查性异常类。
异常
描述
ClassNotFoundException
应用程序在尝试加载类并引发异常时找不到相应的类。
CloneNotSupportedException
当调用Object类中的clone方法来克隆对象,但对象的类无法实现可Cloneable接口时,会引发此异常。
IllegalAccessException
拒绝访问一个类的时候,抛出该异常。
InstantiationException
当试图使用Class类中的newInstance方法创建一个类的实例,而指定的类对象由于是一个接口或一个抽象类而无法实例化时,会引发此异常。
InterruptedException
一个线程被另一个线程中断,抛出该异常。
NoSuchFieldException
请求的变量不存在
NoSuchMethodException
请求的方法不存在
四、异常方法
方法
说明
public String getMessage()
返回有关发生的异常的详细信息,此消息在Throwable类的构造函数中初始化。
public Throwable getCause()
返回一个Throwable 对象代表异常原因。
public String toString()
使用getMessage()的结果返回类的串级名字。
public void printStackTrace()
打印toString()结果和栈层次到System.err,即错误输出流。
public StackTraceElement [] getStackTrace()
返回包含堆栈层次结构的数组。下标为0的元素表示堆栈的栈顶,最后一个元素表示方法调用堆栈的栈底。
public Throwable fillInStackTrace()
用当前的调用栈层次填充Throwable 对象栈层次,添加到栈层次任何先前信息中。
五、捕获异常
使用try和catch关键字捕获异常。try/catch代码块放置在可能发生异常的位置。
try/catch代码块中的代码称为保护代码。使用try/catch的语法如下:
try
{
// 程序代码
}catch(ExceptionName e1)
{
//Catch 块
}
Catch语句包含捕获异常类型的声明。当保护代码块中发生异常时,将检查try后的catch块。
如果发生的异常包含在catch块中,则异常将传递给catch块,这与向方法传递参数相同。
示例:
在下面的示例中,当代码尝试访问数组的第三个元素时,将声明一个包含两个元素的数组并引发异常。
运行结果:
六、多重捕获块
try块后跟多个catch块称为多重捕获块。
多个捕获块的语法如下:
try{
// 程序代码
}catch(异常类型1 异常的变量名1){
// 程序代码
}catch(异常类型2 异常的变量名2){
// 程序代码
}catch(异常类型3 异常的变量名3){
// 程序代码
}
上面的代码段包含三个catch块。
你可以在try语句之后添加任意数量的catch块。
如果保护代码中发生异常,则会将其抛出到第一个catch块。
如果引发异常的数据类型与ExceptionType1匹配,将在此处捕获它。
如果不匹配,则传递给第二个catch块。
所以,直到异常被捕获或通过所有catch块。
示例:
以下示例展示了怎么使用多重 try/catch。
七、throws/throw关键字
如果方法未捕获检查异常,则必须使用throws关键字声明该异常。throws关键字放在方法签名的末尾。
您还可以使用throw关键字抛出异常,不管它是新实例化的还是刚刚捕获的。
以下方法的声明引发RemoteException异常:
一个方法可以声明抛出多个异常,且多个异常之间用逗号隔开。
比如以下的方法声明抛出 RemoteException 和 InsufficientFundsException:
八、finally关键字
finally关键字用于创建在try代码块之后执行的代码块。
无论是否发生异常,finally块中的代码都将执行。
在finally代码块中,可以运行具有finishing up性质的语句,例如cleanup类型。
finally代码块出现在catch代码块的末尾,语法如下:
try{
// 程序代码
}catch(异常类型1 异常的变量名1){
// 程序代码
}catch(异常类型2 异常的变量名2){
// 程序代码
}finally{
// 程序代码
}
示例:
运行结果:
注意事项:
① catch 不能独立于 try 存在。
② 在 try/catch 后面添加 finally 块并非强制性要求的。
③ try 代码后不能既没 catch 块也没 finally 块。
④ try, catch, finally 块之间不能添加任何代码。
九、声明自定义异常
你可以在Java中自定义异常,在编写自己的异常类时,请记住以下几点。
① 所有异常都必须是Throwable的子类。
② 如果要编写checkup异常类,则需要继承该Exception类。
③ 如果要编写运行时异常类,则需要继承RuntimeException类。
可以定义自己的异常类,如下所示:
class MyException extends Exception{
}
通过仅继承Exception类而创建的异常类是检查异常类。
以下insufficientFundsException类是从Exception继承的用户定义的异常类。
与任何其他类一样,异常类包含变量和方法。
示例:
下面的例子是模拟一个银行账户,通过识别银行卡号,就可以存取款了。
要演示如何使用自定义异常类,在以下CheckingAccount类中包含一个withdraw()方法,以抛出一个非充分的FundSexException异常。
下面的BankDemo程序演示如何调用CheckingAccount类的dispose()和withraw()方法。
编译以上三个文件,并运行BankDemo,运行结果如下:
十、通用异常
在Java中定义了两种类型的异常和错误。
1、JVM(Java虚拟机) 异常: 由 JVM 抛出的异常或错误。例如:NullPointerException 类,ArrayIndexOutOfBoundsException 类,ClassCastException 类。
2、程序级异常: 由程序或者API程序抛出的异常。例如 IllegalArgumentException 类,IllegalStateException 类。
以上就是关于大数据编程入门:Java异常处理的全部内容了,希望这篇文章能够帮助到大家~
Java高级编程基础:原子信号量操作实现组线程执行管理
前言
由于Java高级并发编程主要是针对多线程并发访问公共资源控制来展开的,而现在服务器大多都是多核处理,所以在执行控制中,单一的同步锁无法满足需要,为此Java 1.5开始引入了三个重要的概念Semaphores,CountDownLatch和CyclicBarrier 其实这三个实现类都是基于以整型原子操作状态值操作的执行控制类。
严格意义上讲,它们都是对原子操作int类型表示状态来控制锁操作的封装。我们知道,在原子类型操作中,我们避免了使用锁机制而采用CAS机制 达到了操作的原子性不可中断,从而乐观的实现了共享资源的访问。
但是在我们现实开发中,有很多场景需要对多个操作进行分组控制,也就是说允许指定数量的线程进入临界区操作。
这种情况常见于各类池化原理实现上。比如我们有一个提供多线程处理的服务,每次允许5个客户端接入,超过5个就需要排队等待。
如此我们就需要一个组控制机制来实现。为此我们可以封装一个由原子int类型变量表示的计数器,由这个计数器来统计每次进入临界区的线程数量,通过原子读取和增减来决定等待队列线程的获取进入许可,同时当线程离开临界区后,将计数器恢复。
依次来实现对线程的组控制。
信号量
我们可以想象信号量就是一个全局的看护者,它维护着一组许可证,每次有线程想获取一个许可证时它会根据情况阻塞等待许可证是可用状态,如果可用就颁发给线程。每次线程释放许可证,同时也意味着放开对获取许可证的占有,许可证变为可申请。
而实际上,其实并没有真正的许可对象被引用。信号量仅仅是一个计数变量而已。
信号量通常用于限制访问一些物理或逻辑资源的线程的数量。
比如,我们在设计线程池时,就可以定义一个最大线程数的信号量来控制它。
大体思路是,我们设计一个可用的对象实例集合,其长度是线程池的最大数。
然后设计一个其对应状态数组,保存这些对象可用状态。
然后使用同步操作来检查每个对象的对应的状态,如果发现可用对象,就将对象取出使用。
同时维护另外一个同步线程操作检查这些对象状态,如果发现对象可用就标记它为可用状态。
然后我们可以在这个线程池的对外操作时定一个信号量来限制获取线程对象,在线程对象被占满时手动释放线程。
在获得一个项目之前,每个线程必须从信号量那里获得一个许可证,从而保证其操作资源可用。
当线程已经完成了操作离开临界区后,许可就会回到池中和信号量计数相应的递减,允许后续线程获取许可进入。
信号量获取许可调用acquire()方法,可以指定获取数量,默认获取一个许可。
注意,这个获取过程是没有同步锁的,因为一旦加了同步锁将阻止许可被返还个池子中。
信号量封装了限制对池的访问所需的同步,与维护池本身一致性所需的任何同步分开。
初始化为一个信号量的信号量(使用该信号量时最多只能有一个许可证)可以用作互斥锁。
这种信号量常被称为二进制信号量,因为它只有两个状态存在:许可可用或者没有许可可用,
我们使用二进制信号量时,二进制信号量具有这样的属性:
“锁”可以由所有者以外的线程释放!
由于信号量跟普通锁不同,它没有所有权的概念 ,这一点不同于 java.util.concurrent.locks.Lock 的实现。
这在某些特定情形里很有用,比如死锁恢复 。
信号量有个特别之处就是它允许后来先得,也就是说,调用acquire的线程可以在已经等待的线程之前分配一个许可证。
在逻辑上,实际上就是新线程将自己放在等待线程队列的最前面。如此就是高优先级掠夺政策,易造成低优先级线程被饿死。
下面是一个简单的示例来演示信号量的定义和使用:
图 2-1
图2-2
所以,在构建信号量时,我们可以将公平性参数设置为true,信号量保证调用acquire()方法的线程被选中,以获得处理这些方法调用的顺序(FIFO,先进先出)。
注意,不定时的#tryAcquire()该获取方法不尊重公平设置,但会接受任何许可。
通常,用于控制资源访问的信号量应该初始化为公平的,来确保没有线程被饿死。
当将信号量用于其他类型的同步控制时,非公平排序的吞吐量优势常常超过公平考虑。
这个类还提供了方便的方法来#acquire(int)和#release(int)一次获取或释放多个许可证。
所以,我们在使用这些方法时要注意将公平性参数设置为true,避免造成某些线程被无限期延迟的风险增加。
上面示例的执行结果:
另外:内存一致性效应 :调用release()方法之前线程中的操作优先于在另一个线程中跟在一个成功获取acquire()后的行为。
闩锁(CountDownLatch )
CountDownLatch类是JDK中另一个有用的线程同步类。
与信号量类类似,它也提供了一个计数器,但是CountDownLatch的计数器是随着获取许可的线程越多而递减的直到减少到零。
在这过程中它可以阻塞进入的线程等待,等到计数器递减为零,等待的所有线程都可以继续执行。
我们在开发过程中,可能会遇到这样的情况,比如某个应用程序的启动和初始化过程,需要有多个资源同时具备才可以,那么我们通过多个线程来提供这些资源,而必须等待所有资源条件都具备了,应用程序才可以启动执行。如此我们就可以使用这种CountDownLatch来实现。
简单概括来说就是:当池中的所有线程都必须在某个时间点进行同步才能继续运行时,通常需要使用CountDownLatch。
另外一个比较常见的简单的例子是,一个应用程序必须从不同的数据源收集数据,然后才能将新的数据集存储到数据库中。
下面的代码演示了五个线程如何随机休眠一段时间。每一个被唤醒的线程都从锁存器开始计数,然后等待锁存器变为零。
最后,所有线程输出它们已经完成。
运行此示例时,我们将看到输出“等待闩锁”出现在不同的时间点,但是完成每个线程的消息立即打印一个接一个。实现了先到线程等待后到线程到齐,一同开始完成。
循环栅锁(CyclicBarrier)
CyclicBarrier类也实现了一个计数器,从名字中的Cyclic就可以猜到,该计数器具有循环的功能,与CountDownLatch不同,该计数器可以在被计数为零后重置。
所有线程都必须调用其方法await(),直到内部计数器被设置为零。
才会唤醒等待的线程并继续。
同时在内部,计数器被重置为原来的值,整个过程可以重新开始。
这种机制大多用在我们经常需要循环的聚合多种资源重复执行某个动作时采用。
下面是一个简单是示例,来看一下:
图2-1
图 2-1
其执行结果如下:
我们可以看到,在我们指定的时间范围内,三个线程不断的在等待和完成中执行多次。
总结:
上面我们所说的信号量,闩锁,循环栅锁等都是基于无锁的一个原子类型状态表示来实现的,其内在就是一个简单的原子性Int类型状态属性,通过对这个属性的原子读取和增减来作为控制指定数量线程进入临界区操作的许可,从而能够在无锁的情况下,借助CAS操作基础,实现了组线程控制的目的。
总之,只要记住信号量就是一个计数器,它的读取和操作都是原子性的,通过原子性操作的数值来控制线程操作执行。这在现代Java高级并发编程中应用非常广泛,特别是现在充分利用服务器多核并发处理优势的情况下,对于多线程的组控制,已成为开发者必须要了解的重要内容。
相关问答
数字媒体技术专业的课程会涉及到物理吗?
数字媒体技术专业的课程通常不会涉及到大量的物理内容,但是会涉及到一些基础的物理知识。例如,介绍数字信号处理技术的时候会涉及到采样率、量化等相关的物理...
数字媒体技术具体指的是哪些技术?
数字媒体技术具体包括这些技术:平面设计、数字媒体技术基础、信号与系统、计算机图形学﹑数字图像处理﹑计算机视觉、数字媒体非线性编辑技术、人机交互技术、...
从键盘输入一串字符串,编写一个java程序实现统计,输出有几个...
importjava.io.*;importjava.util.*;publicclassStatic{privateStringi...System.out.println(&quo...
短信接口段时间是用人数过多限制发送(不发送的意思)怎么解决...
急急急Java短信接口段时间是用人数过多限制发送(不发送的意思)怎么解决?...使用多线程的信号量工具类,控制下并发数目。短信接口段时间是用人数过多限制...
数字媒体技术考研?
参考内容如下:1、招生院校:浙江大学、中国传媒大学、山东大学、上海大学。2、专业简介:以数字媒体技术研究与开发为切入点,注重技术与内容的融合,在影视、...
数字媒体分几个专业啊?
专业主要有新闻学、传播学、广告学、广播电视新闻学、广播电视编导、编辑出版学、播音与主持艺术、戏剧影视文学、公共关系学、艺术设计、音乐学、戏...摄影...
Javanginx是Java后台开发最常用最入门的技术吗?
没有javanginx这样一个叫法。nginx是最常用的web服务器和反向代理服务器。但是不能解析java,也不是什么java框架。和nginx一类的有个web服务器和java应用服务器...
老铁们我想了解,牡丹江市中学毕业学数字媒体技术应用,数...
[回答]计算机多媒体技术是由计算机技术与数字技术相结合所研发的,应用于信息的收集、处理以及存储。在计算机技术不断创新的过程中,多媒体技术的运用范围...
数字ic选择是什么情况?
[回答]模拟集成电路:主来要是针对模拟信号处理的模块。如;话筒里的声音信号,电视信号和VCD输出的图象信号、温度采集的模拟信号和其它模拟量的信号处理的...
如何看待,哈工大哈工程被禁用matlab?
MATLAB产品族可以用来进行以下各种工作:●数值分析●数值和符号计算●工程与科学绘图●控制系统的设计与仿真●数字图像处理技术●数字信号处理技术●...