JAVA基础篇
HashMap原理
深拷贝与浅拷贝的理解
深拷贝和浅拷贝就是指对象的拷贝,一个对象中存在两种类型的属性,一种是基本数据类型,一种是实例对象的引用。
1.浅拷贝是指,只会拷贝基本数据类型的值,以及实例对象的引用地址,并不会复制一份引用地址所指向的对象,也就是浅拷贝出来的对象,内部的类属性指向的是同一个对象
2.深拷贝是指,既会拷贝基本数据类型的值,也会针对实例对象的引用地址所指向的对象进行复制,深拷贝出来的对象,内部的类执行指向的不是同一个对象
如何查看死锁
1.可以通过jstack命令来进行查看,jstack/jvisualvm命令中会显示发生了死锁的线程
2,或者两个线程去操作数据库时,数据库发生了死锁,这是可以查询数据库的死锁情况
SOL
1、查询是否锁表
show OPEN TABLES wtere In_use 》e;
2、查询进程
show processlist;
3、查看正在锁的事务
SELECT * EROM INFORMATION_SCHEMA.INNODB_LOCKS;
4、查看等待锁的事务
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS;
java死锁如何避免
造成死锁的几个原因:
1.一个资源每次只能被一个线程使用
2.一个线程在阻塞等待某个资源时,不释放已占有资源
3.一个线程已经获得的资源,在未使用完之前,不能被强行剥夺
4.若干线程形成头尾相接的循环等待资源关系
这是造成死锁必须要达到的4个条件,如果要避免死锁,只需要不满足其中某一个条件即可。而其中前3个条件是作为锁要符合的条件,所以要避免死锁就需要打破第4个条件,不出现循环等待锁的关系。
在开发过程中:
1.要注意加锁顺序,保证每个线程按同样的顺序进行加锁
2.要注意加锁时限,可以针对锁设置一个超时时间
3.要注意死锁检查,这是一种预防机制,确保在第一时间发现死锁并进行解决
线程池相关问题
为什么要使用线程池
线程池做的工作主要是控制运行的线程的数量,处理过程中将任务放入队列,然后在线程创建后启动这些任务,如果线程数量超过了最 大数量超出数量的线程排队等候,等其它线程执行完毕,再从队列中取出任务来执行。
主要特点:线程复用;控制最大并发数:管理线程。
第一:降低资源消耗。通过重复利用己创建的线程降低线程创建和销毁造成的消耗。
第二:提高响应速度。当任务到达时,任务可以不需要的等到线程创建就能立即执行。
第三:提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进 行统一的分配,调优和监控
线程池底层工作原理
第一步:线程池刚创建的时候,里面没有任何线程,等到有任务过来的时候才会创建线程。当然也可以调用 prestartAllCoreThreads() 或者 prestartCoreThread() 方法预创建corePoolSize个线程
第二步:调用execute()提交一个任务时,如果当前的工作线程数<corePoolSize,直接创建新的线程执行这个任务
第三步:如果当时工作线程数量>=corePoolSize,会将任务放入任务队列中缓存
第四步:如果队列已满,并且线程池中工作线程的数量<maximumPoolSize,还是会创建线程执行这个任务
第五步:如果队列已满,并且线程池中的线程已达到maximumPoolSize,这个时候会执行拒绝策略,JAVA线程池默认的策略是AbortPolicy,即抛出RejectedExecutionException异常
如何自定义线程池
如何配置合理的线程数
CPU密集型
CPU密集的意思是该任务需要大量的运算,而没有阻塞,CPU一直全速运行。CPU密集任务只有在真正的多核CPU上才可能得到加速(通过多线程),而在单核CPU上,无论你开几个模拟的多线程该任务都不可能得到加速,因为CPU总的运算能力就那些。
CPU密集型任务配置尽可能少的线程数量:一般公式:CPU核数+1个线程的线程池
IO 密集型
由于IO密集型任务线程并不是一直在执行任务,则应配置尽可能多的线程,如CPU核数*2 I0密集型,即该任务需要大量的I0,即大量的阻塞。在单线程上运行I0密集型的任务会导致浪费大量的CPU运算能力浪费在等待。所以在IO密集型任务中使用多线程可以大大的加速程序运行,即使在单核CPU上,这种加速主要就是利用了被浪费掉的阻塞时间。
I0密集型时,cpu核数 / (1-0.9),核数为4的话,一般设置 40
线程池拒绝策略有哪些?
拒绝策略分类 | 含义 | 使用场景 |
---|---|---|
AbortPolicy | 丢弃任务并抛出异常 RejectedExecutionException | 我们项目中关于线程池的定义,使用的就是默认的 如果这种需求是关键的业务,eg:商品详情/购物车/首页 |
DiscardPolicy | 安静的丢弃任务但是不抛出异常 | 设计的时候,一些无关紧要的业务可以采用此策略 Eg:单纯的展示某一项数据的情况 文章的浏览量/点赞个数 |
DiscardOldestPolicy | 丢弃队列最前面的任务,然后重新提交被拒绝的任务 | 喜新厌旧 使用场景不多,可根据特定场景使用 |
CallerRunsPolicy | 由调用线程处理该任务 | 使用场景非常少 |
synchronized和ReentrantLock锁
synchronized | ReentrantLock |
---|---|
关键字 | 类 |
自动加锁和释放锁 | 需要手动调用unlock方法释放锁 |
jvm层面的锁 | API层面的锁 |
非公平锁 | 可以选择公平或者非公平锁 |
锁是一个对象,并且锁的信息保存在了对象中 | 代码中通过int类型的state标识 |
有一个锁升级的过程 | 无 |