线程池:
管理线程创建,销毁的一系列池子
如何创建线程池?
ExecutorService executor = Executors.newFixedThreadPool(n);
创建线程有多种方法,为何要用线程池?
- 减少性能开销,每次执行任务都新建线程
- 造成cpu资源浪费使用线程池可以实现线程的复用
- 通过自定义线程可以适应更多的业务场景,满足需求
线程池的流程?
常用JUC并发类?
- CountDownLatch
- CyclicBarrier
- Semaphore
- 前两者使用较多,不过注意区别,countDownLatch在等待时其他线程已经释放,可以进行其他工作,CyclicBarrier在等待其他线程时不会进行释放
线程池参数有哪些?
1.corePoolSize:线程池中的常驻核心线程数
2.maxinumPoolSize:线程池中能够容纳同时执行的最大线程数
3.keepAliveTime:多余的空闲线程的存活时间
当前线程池数量超过corePoolSize时,当空闲时间达到keepAliveTime时,多余空闲线程会被销毁直到只剩下corePoolSize个线程为止
4.unit:keepAliveTime的单位
5.workQueue:任务队列,被提交但是尚未被执行的任务
6.threadFactory:表示生成线程池中工作线程的线程工厂,用于创建线程一般用默认的即可
7.handler:拒绝策略,表示当队列满了并且工作线程-大于等于线程池的数量最大线程数(maxinumPoolSize)时如何来拒绝请求执行的runnable的策略
锁:
上锁,对资源进行锁定,用来供某些程序读写,其他程序只能等待
悲观锁:在可能会发生并发冲突的情况下,避免一切外来因素对数据造成不完整性的操作
乐观锁:在可能不会发生并发冲突的情况下,在提交之前进行检查
区别:悲观锁不管怎么样,先锁住再说,锁住再读写,多用于写的场景 乐观锁先读写再锁住,多用于读的场景
自旋锁:就是重试,比如你在获取锁的时候已经被其他线程占用了,然后你就等等再尝试
公平锁:这就更好理解了,排队买奶茶,都是老实人,排队就好
非公平锁:插队,但这个插队不是一定会比其他人快,他比起其他人的优势只是少了线程切换之间的开销(也就是一个人买完另一个人才下单这个切换的过程),没抢到还得去排队
可重入锁:允许线程在获取锁之后再次获取同一个锁,而不会被自己持有的锁所阻塞,也就是一个资源上加好几把锁
分布式锁:满足分布式场景,同一时刻只能有一个线程在操作
......
CAS是什么?
其实广泛点来说就是乐观锁,全称是Compare And Swap,一种原子性操作
先读取当前值,再计算预期值,相等就更新为新值,不相等就不管了
适用于具备较低并发竞争的情况,可以提高系统吞吐量和性能
synchronized锁?
其实是一个同步锁,也是一个Java中的关键字,可以加在方法前,那这个方法就是同步方法,在同一时间只能有一个线程访问,直到使用完释放锁之后,其他线程才能继续读写
总结:是一种线程同步机制,是实现线程安全的方法之一
Java中的锁和Mysql中锁的区别和联系?
- 层次不同
Java中的锁是应用层面的锁机制,通过Java语言提供的关键字(synchronized)或Lock接口实现
MySQL中的锁是数据库层面的锁机制,用于控制数据库操作的并发和数据隔离
- 锁的粒度不同
Java中的锁可以是对象级别的锁(synchronized关键字修饰的方法或代码块)或者线程级别的锁(Lock接口的实现类),用于保护共享资源或临界区
MySQL中的锁可以是行表级别的锁或数据库级别的锁,用于控制对数据库对象的访问权限
- 作用范围不同
Java中的锁只在单个Java虚拟机(JVM)内起作用,仅用于线程之间的同步和互斥
MySQL中的锁是在数据库服务端进行控制的,可以跨多个客户端连接和线程,用于控制事务的隔离和并发操作
- 锁的机制不同
Java中的锁采用的是悲观锁机制,即假设并发冲突一定会发生,所以需要加锁来保证数据的一致性和可见性
MySQL中的锁采用的是乐观锁机制和悲观锁机制相结合,通过行级锁、表级锁等方式实现对数据库对象的并发控制
总结:Java中的锁主要用于线程同步和共享资源的互斥访问,而mysql中的锁主要用于数据库事务的隔离和并发操作的控制。它们的作用范围不同,机制不同,但都在不同的层面上提供了并发控制的手段