JUC并发编程小结
- 所谓并发,即多线程操作同一资源,并行(可以理解为多个人一起行走);
- 并发编程本质:充分利用CPU的资源;
- 线程6个状态
- NEW #新生
- RUNNABLE #运行
- BLOCKED #阻塞
- WAITING #等待
- TIMED_WAITING #超时等待
- TERMINATED #终止
- wait/sleep区别
4.1来自不同得类:
wait=>Object
sleep=>Thread
4.2关于锁得释放
wait 会释放锁
sleep不会释放锁
4.3使用的范围不同
wait 必须在同步代码块中
sleep 可以在任何地方
- Synchronized和Lock锁区别:
1. Synchronized 内置的Java关键字;Lock是一个Java类。
2. Synchronized 无法判断获取锁的状态;Lock可以判断是否获取到了锁。
3. Synchronized 会自动释放锁;Lock必须要手动释放!如果不释放锁,死锁。
4. Synchronized 线程1(获得锁)、线程2(等待,傻傻的等);Lock锁就不一定会等待下去。
5. Synchronized 可重入锁,不可以中断的,非公平;Lock,可重入锁,可以判断锁,非公平(可以自己设置,默认非公平)。
6. Synchronized 适合锁少量的代码同步问题;Lock适合锁大量的同步代码;
6.如何解决List和Set 集合的不安全
6.1. List不安全
会导致java.util.ConcurrentModificationException 并发修改异常!
ArrayList 在并发情况下是不安全的
解决方案:
1. vector替代list(并发效率低)
2. 用Collections.synchronizedList(list)包装list(有synchronized修饰的方法效率低)
3. 使用juc里的CopyOnWriteArrayList替代list(推荐使用)写入时复制,读写分离的思想。
CopyOnWriteArrayList使用的是Lock锁,效率会更加高效!
6.2. set 不安全
Set和List同理可得: 多线程情况下,普通的Set集合是线程不安全的;
解决方案还是两种:
1. 使用Collections工具类的synchronized包装的Set类
2. 使用CopyOnWriteArraySet 写入复制的JUC解决方案
7. Callable
1、可以有返回值;
2、可以抛出异常;
3、方法不同,run()/call()
8. 常用的辅助类
1. CountDownLatch(计数器)
主要方法:
countDown 减一操作;
await 等待计数器归零
await 等待计数器归零,就唤醒,再继续向下运行
2. CyclickBarrier(也是计算器)
一般也是用于对多个线程任务进行同步执行,直到所有线程达到结束
3. Semaphore(限流)
原理:
semaphore.acquire()获得资源,如果资源已经使用完了,就等待资源释放后再进行使用!
semaphore.release()释放,会将当前的信号量释放+1,然后唤醒等待的线程!
作用: 多个共享资源互斥的使用! 并发限流,控制最大的线程数!