1. JUC主要的四个包
- java.util.concurrent
- java.util.concurrent.atomic
- java.util.concurrent.locks
- java.util.concurrent.function
2. 线程和进程
- 进程是程序的一次执行过程;
- 线程是比进程更小的执行单位,一个进程可以有多个线程,线程也称为轻量级进程;
- 进程间一般相互独立,同类线程之间可以共享资源;
- Java默认有两个线程:main线程和gc线程;
- 并发是交替执行;
- 并行是一起执行。
- New
- Runnable:- Ready, - Running
- Blocked
- Waiting
- Timed_Waiting
- Terminated
- 属于不同的类:wait属于Object类,sleep属于Thread类;
- 二者都可以暂停线程的运行;
- sleep不释放锁,wait释放锁;
- sleep自动苏醒,wait需要被其他线程唤醒;
- sleep主要用于线程的暂停,wait用于线程间的交互通信;
3. Lock锁
- 公平锁:十分公平,先来后到
public ReentrantLock(boolean fair){
sync = fair ? new FairSync() : new NonfairSync();
}
- 非公平锁 (默认):不公平,可以插队
public Reentrantlock(){
sync = new NonfairSync();
}
- 创建锁:new ReentrantLock();
- 上锁:lock();
- 解锁:unlock()
- Syn是关键字,Lock是一个类;
- Syn无法判断锁的状态,Lock可以判断是否获取到了锁;
- Syn自动释放锁,Lock手动释放锁;
- Syn是非公平锁,Lock可以自己设置;
- Syn适合锁少量的同步代码,Lock适合锁大量的代码。
4. 生产者消费者模式
链接点击跳转
-
注意使用
while()
避免虚假唤醒问题; -
使用
comdition
可实现精准唤醒:condition1.signal(), condition2.signal();
5. 八锁问题分析
链接点击跳转
6. 集合不安全类
- ArrayList不安全, 解决方案:
List<String> list = new Vector<>();
List<String> list = Collections.synchronizedList(new ArrayList<>());
List<String> list = new CopyOnWriteArrayList<>();
- HashSet不安全:
Set<String> set = Collections.synchronizedSet(new HashSet<>());
Set<String> set = new CopyOnWriteArraySet<>();
- HashMap不安全:
Map<Object, Object> map = Collections.synchronizedMap(new HashMap<>());
Map<String, String> map = new ConcurrentHashMap<>();
7. Callable
Callable有返回值,会抛出异常,Runnable并不会;
找到关系
public class Main {
public static void main(String[] args) throws ExecutionException, InterruptedException {
myThread myThread = new myThread();
FutureTask futureTask = new FutureTask(myThread); //适配类
new Thread(futureTask, "xianchengName").start();
Object o = futureTask.get(); //获取callable返回的结果
System.out.println(o);
}
}
class myThread implements Callable {
@Override
public Object call() throws Exception {
return null;
}
}
8. 常用辅助类
- CountDownLatch
原理:每次有线程调用countDown()就-1,当计数器变为0,await()就会被唤醒,继续向下执行;
countDownLatch.countDown(); //数量-1
countDownLatch.await(); //等待计数器归零,再向下执行
- CyclicBarrier
作用与countDownLatch相似;
- Semaphore
可以指定多个线程同时访问某一资源;
并发限流;
控制最大线程数;
9. 读写锁 ReadWriteLock
更加细粒度的锁;
ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock();
//写锁,某一时刻只允许一个线程写
reentrantReadWriteLock.writeLock().lock();
reentrantReadWriteLock.writeLock().unlock();
//读锁,某一时刻允许多个线程读
reentrantReadWriteLock.readLock().lock();
reentrantReadWriteLock.readLock().unlock();
10. 阻塞队列
线程池
方式 | 抛出异常 | 有返回值,不抛异常 | 阻塞等待 | 超时等待 |
---|---|---|---|---|
添加 | add() | offer() | put() | offer( , , ) |
删除 | remove() | poll() | take() | poll( , ) |
检测队首元素 | element() | peek() |
11. 线程池
ExecutorService single = Executors.newSingleThreadExecutor(); //创建单个线程
ExecutorService fixed = Executors.newFixedThreadPool(5); //创建固定大小线程池
ExecutorService cache = Executors.newCachedThreadPool(); //创建可伸缩大小的线程池
public ThreadPoolExecutor(int corePoolSize, //核心线程数
int maximumPoolSize, //最大线程数
long keepAliveTime, //超时没调用者释放时间
TimeUnit unit, //时间单位
BlockingQueue<Runnable> workQueue, //阻塞队列
ThreadFactory threadFactory, //线程工厂,一般不动
RejectedExecutionHandler handler) { //拒绝策略,四种
new ThreadPoolExecutor.AbortPolicy(); //不处理,抛出异常
new ThreadPoolExecutor.CallerRunsPolicy(); //哪里来去哪里
new ThreadPoolExecutor.DiscardPolicy(); //丢弃不处理,不抛异常
new ThreadPoolExecutor.DiscardOldestPolicy(); //尝试和最早的竞争,不抛异常
- CPU密集型:CPU是几核,就等于几,可保持CPU的效率最高;
- IO密集型:一般是程序中十分耗费IO资源线程数的两倍;
12. 四大函数式接口
函数式接口:只有一个函数的接口,如 Runnable;
- 函数型接口:两个参数,一个输入参数,一个输出参数
public interface Function<T, R>{
R apply(T t);
}
- 断定型接口:只有一个输入参数,返回值为boolean型
public interface Predicate<T>{
boolean test(T t);
}
- 消费型接口:只有一个输入参数
public interface Consumer<T>{
void accpet(T t);
}
- 供给型接口:只有一个返回值
public interface Supplier<T>{
T get();
}
13. Stream 流式计算
14. ForkJoin
分支计算
15. 异步回调
16. JMM
线程可以将变量保存到本地内存,而不是直接在主内存中进行读写;这样,可能造成一个线程在主内存中修改了变量的值,而另一个线程还使用着这个变量在本地内存的拷贝,可能会造成数据不一致。使用volatile关键字表示这个变量是不稳定的,每次都要在主内存中进行读取。
- lock(),
- unlock(),
- read(),
- load(),
- use(),
- assign(),
- write(),
- store()
17. Volatile
- 保证可见性
- 不保证原子性
- 避免指令重排
答:使用原子类java.util.concurrent.atomic
import java.util.concurrent.atomic;
private volatile static AtomicInteger atomicInteger = new AtomicInteger();
- volatile是线程同步的轻量级实现,性能要比Syn好,但volatile只能修饰变量,而Syn能修饰方法和代码块;
- volatile可以保证可见性,但不能保证原子性,Syn都可以保证;
- volatile更多是用于解决线程间变量的可见性问题,而Syn更多用于线程间访问资源同步性问题。
18. 单例模式
链接点击跳转
19. 深入理解CAS
CAS:比较并交换
AtomicInteger atomicInteger = new AtomicInteger();
//达到期望值就更新,否则就不更新
boolean b = atomicInteger.compareAndSet(1, 2);
20. 原子引用
AtomicReference<Object> objectAtomicReference = new AtomicReference<>();
AtomicStampedReference<Object> objectAtomicStampedReference = new AtomicStampedReference<>();
21. 各种锁的理解
- 公平锁,非公平锁;
- 可重入锁(递归锁);
- 自旋锁;
- 死锁:两个线程互相拥有着对方所需求的资源,且不释放;