3.13学习内容:知识周总结

本文详细介绍了Java中的异常处理,包括异常的分类、如何手动抛出异常、受查异常与运行时异常的区别,以及try-catch-finally语句块的使用。此外,还深入讲解了多线程的概念,特别是线程池的工作原理,提到了ExecutorService接口、FixedThreadPool和CachedThreadPool的使用。还探讨了Callable接口、Future接口以及同步与异步的概念。最后,涉及了Lock接口中的ReentrantLock以及读写锁ReentrantReadWriteLock,以及并发集合的相关知识,如Collections的工具方法、CopyOnWriteArrayList和ConcurrentHashMap等。
摘要由CSDN通过智能技术生成

异常

一切错误或异常的父类: Throwable 位于java.long包中

-Error : JVM、硬件、执行逻辑错误,不能手动处理

-Exception:程序在运行和配置中产生的问题:
-RuntimeException:运行时异常,可处理,可不处理
-CheckedException:受查异常,必须处理

手动抛出异常: throw new 异常类型(“实际参数”) //实际参数即使 message 可以是对异常的具体描述

受查异常: throws声明已成 必须修饰在方法参数列表的后端
运行时异常: 可处理可不处理 无需声明异常

try {} catch{}finally 对于异常的处理
具体形式:
try{
//可能出现异常的代码
}catch(Exception e){
异常处理的相关代码: getMessage() 、printStackTrace()
}finally{
无论有无异常,都需要执行的内容,用于释放资源
}

根据具体需要 自行使用try catch 与 finally
注意:多重catch,应遵循从子到父的顺序,父类异常在最后

自定义异常 :
需要继承自:Exception或它的子类 常用RuntimeException
两种构造方法:
无参构造
String message 参数的构造方法

方法覆盖:
方法名、参数列表、返回值类型必须和父类相同
子类的访问修饰符和父类相同或是更宽
子类中的方法,不能抛出比父类更多、更宽的异常

多线程

线程相关的知识点在笔记中

重难点: 高级多线程

线程池原理:
将任务提交给线程池,由线程池分配线程、运行任务,并在当前任务结束后复用线程。
个人理解
大致理解:线程池中由多个线程组成,例如线程池中有5个线程,那即表明,这个线程池可以同时由5个任务调用;如果调用了6个任务,则第六个任务会在第一个线程完成之后,再次复用线程池里的线程,继续完成任务
注意,可以调用线程池中的线程的是实现了Runnable 或 Callable接口的任务 ,而不是线程!!!

常用的线程池接口和类(所在包:java.util.concurrent):
Executor:线程池的顶级接口。
ExecutorService:线程池接口,可通过submit(Runnable task)提交任务代码。
声明一个线程池 用ExceutorService接受 例如:
ExecutorService es = new 两种方式
第一种 : new FixedThreadPool(int nThreads) 获取固定数量的线程池,参数代表线程池中的线程数量
第二种:new CachedThreadPool() 获得动态数量的线程池,如果不够则创建新的,没有上限。

Callable接口:
具体形式:
public interface Callable{
public V call() throws Exception;
}

与Runnable接口类似,也是声明可执行的任务;
但是Callable具有泛型返回值,并且可以声明异常

Future接口

概念: 异步接收ExceptionService.submit()所返回的状态结果,当中包含了call方法的返回值
方法: V get() 以阻塞形式等待Future中的异步处理结果(call()的返回值)

同步与异步:

同步:
形容一次方法调用,同步一旦开始,调用者必须等待该方法返回,才能继续。

个人理解: 所有在线程之前学习的方法的调用都是同步的,主函数中调用某一方法,运行过程会先执行此方法,当方法执行完毕,然后在回到主函数,继续向下执行。

异步:形容一次方法调用,异步一旦开始,像是一次消息传递,调用者告知之后立刻返回,二者竞争时间片,并发执行

个人理解:异步即是单核CPU执行多个进程的情况,多个进程同时进行。

Lock接口:

常用方法
void lock(); 获取锁,如锁被占用,则等待。
boolean tryLock() 尝试获取锁(成功返回true 失败返回false 不阻塞)
void unlock 释放锁

重入锁
ReentrantLock 这是Lock 接口的一个实现类, 声明:
Lock lock =new ReentrantLock();
这是创建重入锁对象

注意:
我们在调用lock.lock()之后,说明开启锁,但是如果在程序执行过程中,出现了异常,程序就会终止,这样,锁就不会被释放,所以,我们一定要保证,无论程序出现异常与否,我们都要保证在最终释放锁,即lock.unlock(),实现的方法就是,利用try finally 异常处理方法, 将释放锁的方法调用放入finally中,这样是否出现异常都不影响释放锁。

读写锁

此类不是Lock接口的实现类,不可用Lock接口指向该类对象
ReentrantReadWritrLock
这是一种支持一写多读的同步锁,读写分离,可分别分配读锁,写锁
支持多次分配读锁,使多个读操作可以并发执行
声明:
ReentrantReadWriteLock lock=new ReentrantReadWriteLock();
声明读写锁:读锁与写锁是分离的
ReadLock readLock=lock.readLock();
WriteLock writelock=lock.writeLock();

CopyOnWriteArrayList是加强版的读写分离

互斥规则:
写-写:互斥 堵塞
读-写:互斥,堵阻塞写,写阻塞读
读-读:不互斥,不堵塞
意思就是写一次锁需要1秒的话,写5次就是5秒,因为写写互斥,写完一次才能进行下一次,而读读不互斥,意思就是可以并发执行读操作,一秒内执行多次读操作

Collections中的工具方法
获得线程安全集合的方法:后面即是对应的安全线程集合
public static Collection synchronizedCollectoion(Collection c)
public static List synchronizedList(List list)
public static SetsynchronizedSet(Set s)
public static<k,v>Map<K,V>synchronizedMap(Map<k,v> m)
public static SortedSetsynchronizedSortedSet(SortedSet s)
public static<K,V>SortedMap<K,V>synchronizedSortedMap(SortedMap<k,v> m)

接口统一、维护性高,但性能没有提升,均以synchronized实现

其中的一种声明方法:
List safeList = Collections.synchronizedList(list);
得到一个synchronized实现的List集合
SynchronizedList里的add方法里加了个锁

CopyOnWriteArrayList
是ReentrantReadWritrLock的加强版
线程安全的ArrayList,加强版读写分离
写有锁,读无锁,读写之间不堵塞,优于独写锁
写入时,先copy一个容器副本,再添加信元素,最后替换引用
使用方式与ArrayList无异
ReentrantReadWritrLock 与 CopyOnWriteArrayList 的异同
相同:都是读写分离

不同:ReentrantReadWritrLock 写与读互相堵塞,而CopyOnWriteArrayList通过copy源集合的方式,得到新旧两个集合,写访问的是新集合,读访问的是旧集合,当写操作完成之后,会替换掉旧的集合,然后才可以读相应的内容,意思就是读与写不互斥。

内部流程:
在底层方法中,首先会copy一份原有的List,然后读写不阻塞,是因为,读操作的是旧的集合,而写操作的是新copy的集合,在完成写操作之后,会将旧的集合替换掉,所以读写不阻塞;每调用一次,底层方法就会扩容一次,表面使用的是add方法,底层实际是用的CopyOnWriteArrayList的addIfAbsent()来判断要插入的新值是否存在

CopyOnWriteArraySet
理解等同于CopyOnWriteArrayList,但是依旧保留它的特征,无序、无下标、不存在重复元素

ConcurrentHashMap
初始容量默认16段(Segment),使用分段锁设计。
不对整个Map加锁,而是为每个Segment加锁
当多个对象存入同一个Segment时,才需要互斥。
最理想状态为16个对象分别存入16个Segment,并行数量16
使用方式与HashMap无异

理解:当向此实现类中存入对象时,如果两个对象分别存入不同的Segment中时,可以同时进行,不会阻塞,但是当两个对象存入同一个Segment时 ,先得到锁的对象先进入,同步锁锁的是表头对象,拿到锁的对象要先做节点遍历。查看有没有相同的key,相同覆盖,不同,则挂在最后一个节点的next上
Queue接口(队列)

Collection的子接口,表示队列 FIFO(先进先出)
常用方法:
抛出异常:
boolean add(E e)顺序添加一个元素(到达上限后,再添加则抛出异常)
E remove()获得第一个元素并移除(如果队列没有元素时,则抛异常)
E element()获得第一个元素(如果队列没有元素时,则抛异常)
返回特殊值:推荐使用
boolean offer(E e)顺序添加一个元素(到达上线后,在添加则返回false)
E poll()获得第一个元素并移除(如果队列没有元素,则返回null)
E keep() 获得第一个元素但不移除(如果队列没有元素,则返回null)

抛出异常中的方法, 和List中的方法名称一致

ConcurrentLinkedQueue

线程安全、可高效读写的队列,高并发下性能最好的队列
无锁、CAS比较交换算法,修改的方法包含三个核心参数(V,E,N)
V:要更新的变量 E:预期值 N:新值
只有当V==E时,V=N;否则表示已被更新过,则取消当前操作

注意:
用Queue接口声明LinkedList实现类时,可以调用LinkedList的方法来打乱队列FIFO的规则 例如 用link.add(0,“x”)方式,就改变了队列的头部元素

CAS比较交换算法保持了队列中元素不可重复

BlockingQueue接口(阻塞队列)
Queue的子接口,阻塞的队列,增加了两个线程状态为无限期等待的方法
方法:
void ptu(E e) 将指定元素插入此队列中,如果没有可用空间,则等待
E take() 获取并移除此队列头部元素,如果没有可用元素,则等待

可以用来解决生产者、消费者问题

阻塞队列的两种实现类:
ArrayBlockingQueue:
数组结构实现,有界队列(手工固定上限) 参数为队列长度
BlockingQueue abq=new ArrayBlockingQueue(10)

LinkedBlockingQueue
链表结构实现,无界队列(默认上限Integer.MAX_VALUE)
BlockingQueue lbq=new LinkedBlockingQueue();

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值