这次讲了异常
程序在运行过程中出现的特殊情况。
Throwable 一切错误或异常的父类。
Error:JVM、硬件、执行逻辑错误,不能手动处理;
Exception:程序在运行和配置中产生的问题,可处理;
Exception子类RuntimeException:运行时异常,可处理,可不处理;
Exception子类CheckedException:首查异常,必须处理;
自动抛出异常:当程序在运行过程中遇到不符合规范的代码或结果时,会产生异常;
手动抛出异常:语法 throw new 异常类型(“实际参数”);
throw new RuntimeException();
throw new CheckedException();
产生异常的结果:相当于遇到 return 语句,导致程序终止;
异常的传递:按照方法的调用链反向传递,如始终没有处理异常,最终会由JVM进行默认异常处理(打印堆栈信息);
public static void main(String[] args) throws Exception{
m1();
}
public static void m1() throws Exception{
m2();
}
public static void m2() throws Exception{
throw new Exception();
}
受查异常:throws 声明异常,修饰在方法参数列表后端;
运行时异常:因可处理可不处理,无需声明异常;
异常的处理:
try{
可能出现的异常代码;
}catch(Exception e){
异常处理相关代码;
e.getMessage();获取异常详细信息
e.printStackTrace();打印堆栈跟踪信息
}finally{
无论如何都会执行的代码结构,用于释放资源
}
常见异常处理结构
try{
}catch{
}
---------------
try{
}catch{
}catch{
}
----------------
try{
}catch{
}finally{
}
----------------
try{
}catch{
}catch{
}finally{
}
自定义异常:
继承Exception或Exception子类;常用于RuntimeException;
必要提供构造方法:无参构造;String message参数构造方法;
方法覆盖:
方法名、参数列表、返回值类型必须和父类相同;
自类访问修饰符和父类相同或者比父类更宽;
子类中的方法,不能抛出比父类更宽泛的异常。
多线程
线程,又称轻量级进程。程序中的一个顺序控制流程,同时也是CPU的基本调度单位。进程由多个线程组成,彼此间完成不同的工作,交替执行,称为多线程。
线程的组成:
CPU时间片:操作系统(OS)会为每个线程分配执行时间。
运行数据:
堆空间:存储线程需要使用的对象,多个线程可以共享堆中的对象;
栈空间:存储线程使用的局部变量,每个线程都拥有独立的栈;
线程逻辑代码;
创建线程:
public class TestCreateThread{
public static void main(String[] args){
MyThread t1=new MyThread(); 创建子类对象
t1.start(); 调用start()方法
}
}
class MyThread extends Thread{ 继承Thread类
public void run(){ 覆盖run()方法
for(int i=0;i<50;i++){
System.out.println("MyThread:"+i);
}
}
}
创建线程2:
public class TestCreateThread{
public static void main(String[] args){
MyRunnable mr=new MyRunnable();
Thread t2=new Thread(mr);
t2.start();
}
}
class MyRunnable implements Runnable{
public void run(){
for(int i=0;i<50;i++){
System.out.println("MyRunnable:"+i);
}
}
}
线程的状态(基本)
New(初始状态)——>Ready(就绪状态)——>Running Man(运行状态)——>Terminate(结束状态)
常见方法:
休眠:
public static void sleep(long millis) 当前线程主动休眠时间( 单位毫秒);
放弃:
public static void yield() 当前线程主动放弃时间片,回到就绪状态,竞争下一次时间片
结合:
public final void join() 允许其他线程加入到当前线程中
线程安全问题:
当多线程并发访问共享资源时,一次仅允许一个线程使用,才可保证其准确性。
保证线程同步:
同步代码块(1):
sybchronized(临界资源对象){ 对临界资源对象加锁
代码(原子操作)
}
每个对象都有一个互斥锁标记,用来分配给线程;
只有拥有对象互斥锁标记的线程才能进入对该对象加锁的同步代码块;
线程退出同步代码块时,会释放相应的互斥锁标记;
同步代码块(2):
synchronized 返回值类型 方法名称(形参列表){对当前对象(this)加锁
代码(原子操作)
}
只有拥有对象互斥锁标记的线程,才能进入该对象加锁的同步方法中;
线程退出同步方法时,会释放相应的互斥锁标记。
线程通信:
等待:
public final void wait()
public final void wait(long timeout)
线程进入等待状态,退出竞争时间片;
通知:
public final void notify()
public final void natifyAll()
线程被唤醒,继续竞争时间片;
高级多线程
线程池:
线程容器,可设定线程分配的数量上限。
将预先创建的线程对象存入池中,并重用线程池中的线程对象。
避免频繁的创建和销毁。
获取线程池:
常用线程池接口(所在包 java.util.concurrent)
Executor:顶级接口
ExecutorService:线程池接口,可通过submit(Runnable task)提交任务代码
Executors :可获得一个线程池
newFixedThreadPool(int nThreads)获取固定数量线程池。
newCacheedThreadPool()获得动态数量的线程池,无上限。
Callable接口
public interface Callable<V>{
public V call() throws Exception;
}
与 Runnable 接口类似,具有泛型返回值;
Future接口
异步接受ExecutorService.submit()所返回的状态结果,当中包含了call()的返回值
方法:V get()以阻塞的形式等待Future中的异步处理结果(call()的返回值)
线程同步:一次方法调用,同步一旦开始,调用者必须等待该方法返回,才能继续。
线程异步:一次方法调用,异步一旦开始,像是一次消息传递,调用者告知之后立刻返回。二者竞争时间片,并发执行。
Lock接口:
常用方法:
void lock() 获取锁,如果锁被占用则等待。
boolean tryLock() 尝试获取锁
void unlock() 释放锁
重入锁
class MyList{
private Lock locker=new ReentrantLock(); 创建重入锁对象
private String[] strs={"A","B","","",""};
private int count=2;
public void add(String value){
locker.lock(); 显示开启锁
try{
strs[count]=value;
try{
Thread.sleep(1000);
}catch(InterruptedException e){}
count++;
}finally{
locker.unlock(); 显示释放锁
}
}
读写锁
class MyClass{
ReentrantReadWriteLock rwl=new ReentrantReadWriteLock();
ReadLock readLock=rwl.readLock();
WriteLock writeLock=rwl.writeLock();
private int value;
public int getValue(){
readLock.lock(); 开启读锁
readLock.unlock(); 释放读锁
return null;
}
public void setValue(int value){
writeLock.lock(); 开启写锁
writeLock.unlock(); 释放写锁
}
}
线程安全集合
CopyOnWriteArrayList
CopyOnWriteArraySet
ConcurrentHashMap
Queue接口
ConcurrentLinkedQueue
BlockingQueue接口(阻塞队列)
ArrayBlockingQueue
LinkedBlockingQueue
来源:CSDN
作者:熊猫小飞侠
链接:https://blog.csdn.net/qq_37504120/article/details/104873412