乐观学习,乐观生活,才能不断前进啊!!!
我的主页:optimistic_chen
我的专栏:c语言 ,Java
欢迎大家访问~
创作不易,大佬们点赞鼓励下吧~
文章目录
- JUC组件
- ReentrantLock与synchronized的区别
- Semaphore信号量
- CountDownLatch
- 线程安全的集合类
- 多线程环境下使用ArrayList
- 多线程环境下使用队列
- 多线程使用Hash表
- 完结
JUC组件
JUC( java.util.concurrent ) :是和多线程相关的工具。
Callable接口与之前的Runnable接口是并列关系,二者的主要区别在于对程序运行结果的获取
但是Thread的构造方法没有提供版本去传入Callable对象: Thread只是一个线程,它的重点在于完成任务,而不是获取到完成任务后的结果。
如果我们想要得到任务完成后的结果,需要有一个“中间人”帮助。
FutureTask就是这个中间人,它获取到任务的结果,在把它交给线程,由线程来获取FurtureTask对象,即拿到任务结果。
ReentrantLock与synchronized的区别
首先都是可重入锁
区别:
1. synchronized是关键字,通过JVM内部C++实现的;ReentrantLack是Java标准库的类
2. synchronized通过代码块控制加锁解锁;ReentrantLock需要lock/unlock方法
3. ReentrantLock还有tryLock()方法,判断加锁成功返回true,加锁失败返回false(不会阻塞)
4. ReentrantLock提供了公平锁的效果。(默认非公平)
5. ReentrantLock搭配的等待通知机制,是Condition类。相比较wait notify来说更加强大
Semaphore信号量
本质:协调多个进程(线程)之间的资源分配,可以理解为计数器:描述资源的个数
申请一个资源,计数器-1 — P操作
释放一个资源,计数器+1 — V操作
信号量初始值为1的情况,取值要么是1,要么是0:等价于锁
CountDownLatch
我们使用多线程的目的是为了提高重程序运行效率,通过把一个大任务分解为多个小人物来实现,使用多个线程来解决这些小任务,从而完成大任务。那么我们如何得知,这个大任务什么时候完成?
1. 构造方法指定一个参数,描述一个拆分了多少个任务
2. 每个任务执行完成后,都调用一次countDown方法
3. 主线程重调用await方法,等待所有任务执行完毕,await返回/阻塞等待
线程安全的集合类
多线程环境下使用ArrayList
- 自己加锁:具体情况,具体分析
- Collection.synchronizedList(new ArrayList)提前嵌套,返回的List的各种关键方法都是带有synchronized
- 使用CopyOnWriteArrayList(写时拷贝),不用锁
多线程环境下使用队列
1. ArrayBlockQueue:基于数组实现的阻塞队列
2. LinkedBlockingQueue:基于链表实现的阻塞队列
3. PriorityBlockingQueue:基于堆实现的带优先级的阻塞队列
4. TransferQueue:最多只含有一个元素的阻塞队列
多线程使用Hash表
HashMap线程不安全
Hashtable线程安全(给public方法都加了synchronized)
ConcurrentHashMap线程安全,效率更高
因为它是按照桶级别进行加锁,而不是给hash加一个全局锁,降低锁冲突概率
优化点:
1. 把锁整个hash表 优化 为锁桶
2. 使用原子类针对size进行维护
3. hash扩容时,化整为零
完结
可以点一个免费的赞并收藏起来~
可以点点关注,避免找不到我~ ,我的主页:optimistic_chen
我们下期不见不散 ~ ~ ~