juc并发(自用)

JUC: java.util.concurrent
java默认两个线程,main、GC线程
java开不了线程,只能通过native方法执行
wait/sleep的 区别:来自不同类wait在object是实例方法,需要notify或notifyAll唤醒,sleep在Thread是静态方法,超时或interrupt,wait释放锁,sleep不会释放锁,wait只能在同步代码块中使用,sleep什么地方都可以,sleep需要捕获异常(InterruptedException),而wait需要
lock:ReentrantLock , ReentrantReadWriteLock.ReadLock , ReentrantReadWriteLock.WriteLock
公平锁:先来后到 非公平锁:可以插队(默认)
Synchronized与lock的区别:
Synchronized是内置的java关键字,Lock是一个类
Synchronized无法判断锁的状态,Lock可以判断是否获取到了锁,
Synchronized会自动释放锁,Lock必须要手动释放锁finally
Synchronized获得不到锁,会一直等待,Lock可以尝试获取锁,不需要一直等待
Synchronized可重入、不可中断,非公平,Lock可重入,可中断,公平/非公平
Synchronized适合锁少量的代码同步问题,Lock适合锁大量的同步代码
java虚假唤醒:需要将if语句修改为while
JUC8锁问题:谁先拿到锁谁先执行,锁的对象是方法的调用者
没有加synchronized的普通方法不受锁的影响
ConcurrentModificationException并发修改异常
并发下:ArrayList不安全的解决方案:
Vector<>() Collections.synchronizedList(new ArrayList<>());List list = new CopyOnWriteArrayList<>();
java COW写时复制,添加元素时,先复制一份数组,向新数组中添加元素,然后再将原容器的引用指向新容器。实现写时可读,读写分离,应用于读多写少,在写入时加lock,避免复制多份数据。适用于读多写少,缺点就是内存占用,内存压力大,引起频繁的GC,弱一致性,
HashSet set = new HashSet<>();
Set set = Collections.synchronizedSet(new HashSet<>());
Set set = new CopyOnWriteArraySet<>();
Callable 与Runnable区别:可以有返回值,可以抛出异常,方法不同run()/call,
String o = (String) task.get() 可能会阻塞,因为call方法中可能会耗时
new Thread(task).start();
new Thread(task).start();两次执行,只会执行一次call,因为futuretask在调用run方法时,会判断其线程状态,是否为new 不为new则直接返回。
CountDownLatch 是一个计数器,await方法会在计数为0的时候执行。
CyclicBarrier cyclicBarrier = new CyclicBarrier(7, ()->{
System.out.println(“chengong”);
}); 加法计数器,cyclicBarrier.await();调用7次await方法后,就可执行CyclicBarrier
Semaphore semaphore = new Semaphore(3) 信号量,同时访问资源的线程个数
当为1时,可实现互斥锁

读写锁,写锁是独占锁,读锁是共享锁
阻塞队列当队列为空或满时阻塞,非阻塞队列,当满时或空时,报错

ArrayBlockingQueue arrayBlockingQueue = new ArrayBlockingQueue<>(3);
同步队列 SynchronousQueue 容量为1,put,take
线程池:池化技术 创建和销毁十分的浪费资源
优点:降低资源的消耗,提高响应速度,方便管理,线程复用,可以控制最大并发数、管理线程
三大方法、七大参数、四种拒绝策略

7大参数:
public ThreadPoolExecutor
(int corePoolSize,核心线程数
int maximumPoolSize,最大线程数
long keepAliveTime,线程空闲时最大存活时间
TimeUnit unit,最大存活时间单位
BlockingQueue workQueue,任务队列
ThreadFactory threadFactory,线程工厂用默认的即可
RejectedExecutionHandler handler)线程池和队列都满时的拒绝策略

四种拒绝策略:AbortPolicy:丢弃任务并抛出RejectedExecutionException异常 DiscardPolicy:丢弃任务,但是不抛出异常 DiscardOldestPolicy :丢弃队列最前面的任务,然后重新提交被拒绝的任务。CallerRunsPolicy:由调用线程处理该任务
Runtime.getRuntime().availableProcessors() 获取cpu核数
怎么设置线程池的最大值:
对于cpu密集型,可以设置为CPU核数,cpu利用率区域100%。
对于IO密集型,可以设置为2*io线程
函数式接口:

断定性接口:输入一个参数,返回布尔值

消费型接口:只输入不返回 供应型接口:只输出,不输入

JDK1.8新特性:lambda表达式,函数式接口,链式编程,Stream流式计算
Strea流式计算:

forkjoin:拆分任务,汇总结果。
工作窃取:双端队列,某个线程从其他队列里窃取任务来执行,提高效率,但是队列里只有一个任务时也会竞争,且该算法浪费资源
并行流计算,reduce从0开始,
long sum = LongStream.rangeClosed(0L,10_0000_0000L).parallel().reduce(0, Long::sum);
Volatile:是java虚拟机提供的轻量级同步机制

  1. 保证可见性 java编程语言允许线程访问共享变量,为了确保共享变量能被准确和一致地更新,线程应该确保通过排他锁单独获得这个变量。MESI协议
  2. 不保证原子性 可以使用原子类解决或者lock或Synchronized
  3. 禁止指令重排 内存屏障
    JMM,java内存模型,
    8种操作每一种都是原子操作
    lock(锁定):作用于主内存,它把一个变量标记为一条线程独占状态;
    read(读取):作用于主内存,它把变量值从主内存传送到线程的工作内存中,以便随后的load动作使用;
    load(载入):作用于工作内存,它把read操作的值放入工作内存中的变量副本中;
    use(使用):作用于工作内存,它把工作内存中的值传递给执行引擎,每当虚拟机遇到一个需要使用这个变量的指令时候,将会执行这个动作;
    assign(赋值):作用于工作内存,它把从执行引擎获取的值赋值给工作内存中的变量,每当虚拟机遇到一个给变量赋值的指令时候,执行该操作;
    store(存储):作用于工作内存,它把工作内存中的一个变量传送给主内存中,以备随后的write操作使用;
    write(写入):作用于主内存,它把store传送值放到主内存中的变量中。unlock(解锁):作用于主内存,它将一个处于锁定状态的变量释放出来,释放后的变量才能够被其他线程锁定;
    规则:
    (1)不允许read和load、store和write操作之一单独出现(即不允许一个变量从主存读取了但是工作内存不接受,或者从工作内存发起会写了但是主存不接受的情况),以上两个操作必须按顺序执行,但没有保证必须连续执行,也就是说,read与load之间、store与write之间是可插入其他指令的。
    (2)不允许一个线程丢弃它的最近的assign操作,即变量在工作内存中改变了之后必须把该变化同步回主内存。
    (3)不允许一个线程无原因地(没有发生过任何assign操作)把数据从线程的工作内存同步回主内存中。
    (4)一个新的变量只能从主内存中“诞生”,不允许在工作内存中直接使用一个未被初始化(load或assign)的变量,换句话说就是对一个变量实施use和store操作之前,必须先执行过了assign和load操作。
    (5)一个变量在同一个时刻只允许一条线程对其执行lock操作,但lock操作可以被同一个条线程重复执行多次,多次执行lock后,只有执行相同次数的unlock操作,变量才会被解锁。
    (6)如果对一个变量执行lock操作,将会清空工作内存中此变量的值,在执行引擎使用这个变量前,需要重新执行load或assign操作初始化变量的值。
    (7)如果一个变量实现没有被lock操作锁定,则不允许对它执行unlock操作,也不允许去unlock一个被其他线程锁定的变量。
    (8)对一个变量执行unlock操作之前,必须先把此变量同步回主内存(执行store和write操作)。
    单例模式:饿汉式,初始化就new对象,懒汉式,用的时候在new对象

暴力反射可以破坏此单例。
cas:比较并交换,ABA问题
乐观锁:cas+版本号 原子引用
lock的lock和unlock必须配对
可重入锁:可以多次获得同一锁。
悲观锁:在修改数据之前先锁定
乐观锁:乐观锁假设数据一般情况不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果冲突,则返回给用户异常信息,让用户决定如何去做。适用于读多写少的场景,
自旋锁(spinlock):是指当一个线程在获取锁的时候,如果锁已经被其它线程获取,那么该线程将循环等待,然后不断的判断锁是否能够被成功获取,直到获取到锁才会退出循环。
死锁排查:jps -l,查看进程,jstack 进程号查看
排查问题:日志,堆栈信息,

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

徒手写bug326

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值