JUC简短回顾

回顾多线程

线程生命周期

NEW RUNNABLE BLOCKED WAITTING TIME_WAITTING TERMINATED

wait/sleep区别

wait来自object,sleep来自thread
wait会释放锁,sleep不会释放锁
使用范围:
wait 需要在同步代码块中使用
sleep可以在任何地方使用

lock锁

实现类:
ReentranLock ReentrantReadWriteLock ReadLock ReentranReadWriteLock WriteLock

syncronized与lock 的区别:

  • sy是java的关键字,lock是一个java类
  • sy 无法判断获取锁的状态,lock可以判断是否获取锁
  • sy会自动释放锁,lock必须手动释放,否则会发生死锁
  • sy被一个线程获得后另外线程只能等待,lock就不会
  • sy可重入锁,不可以中断,非公平;lock可重入锁,可以判断锁,默认非公平(可以自己设置)
  • sy适合锁少量的代码;lock适合锁大量的代码

传统生产者与消费者、防止虚假唤醒

生产者消费者模式

package com.kuang.pc;

/**
 * @author S_J
 * @version 1.0
 * @date 2022/10/14 20:09
 */
public class A {
    public static void main(String[] args) {
        Date date = new Date();
        new Thread(()->{
            for (int i=0;i<10;i++){
                try {
                    date.incr();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"A").start();

        new Thread(()->{
            for (int i=0;i<10;i++){
                try {
                    date.decr();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"B").start();


    }
}
//等待   业务   通知
class Date{
    private int number = 0;
    //+1
    public synchronized void incr() throws InterruptedException {
        if(number!=0){
            //等待
            this.wait();
        }
        number++;
        System.out.println(Thread.currentThread().getName()+"=>"+number);
        this.notifyAll();
    }
    public synchronized void decr() throws InterruptedException {
        if (number==0){
            //等待
            this.wait();
        }
        number--;
        System.out.println(Thread.currentThread().getName()+"=>"+number);
        this.notifyAll();
    }
}

在这里插入图片描述
当生产者与消费者各位两个实例是,A、C为生产者B、D为消费者
生产者生产完毕后处于等待,阻塞住,唤醒两个消费者
消费者C被唤醒后抢到锁并消费后又处于等待,等待的时候会释放锁
这时消费者D会在wait()后面继续执行
由于前面判断是if
所以不会返回再判断
就继续往下执行
当将if改为while判断语句时
在程序要跳出循环前会进行语句判断
B减过一次资源已经为0
D唤醒后就会进入循环发现为0就会进入循环体就会调用wait()方法进入等待

八锁问题

CopyOnWriteArrayList

并发修改异常
在这里插入图片描述

//Exception in thread "Thread-12" java.util.ConcurrentModificationException并发修改异常
public class ListTest {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        for (int i = 1; i <=10; i++) {
            new Thread(()->{
                list.add(UUID.randomUUID().toString().substring(0,5));
                System.out.println(list);
            }).start();

        }
    }
}

在这里插入图片描述

解决:
改用安全的集合如Vectory或者用Collection.synchronized或者CopyOnWriteArrayList(写入时复制)
另外针对上面代码而言,新加入后集合长度改变了继续使用该集合进行遍历会报并发修改异常,因此当我们add()后就break循环,就重新进行获取新的已经替代后的集合状态
在这里插入图片描述

线程池

线程池的好处:降低资源消耗、提高响应的速度、方便管理、线程复用可以控制最大并发数、管理线程
三大方法、七大参数、四种拒绝策略

三大方法Executors工具类的三个创建线程的方法,分别为:单个SingleThreadPool、固定大小FixedThreadPool、伸缩可变大小CachhedThreadPool

七大参数:核心、最大线程数、超时等待、超时单位、阻塞队列、线程工厂、拒绝策略

四种拒绝策略AbortPolicy默认拒绝策略,拒绝任务并抛出任务、CallerRunsPolicy使用调用线程直接运行任务、DiscardPolicy直接拒绝任务,不抛出错误、DiscardoldestPolicy触发拒绝策略,只要还有任务新增,一直会丢弃阻塞队列的最老的任务,并将新的任务加入

最大线程到底如何定义?如下

CPU密集型IO密集型

CPU密集型:几核就定义为几,可以保证效率最高。获取CPU的核数:sout(Runtime.getRuntime().availableProcessors())
IO密集型:判断程序中十分耗IO的线程。如15个大型任务,Io十分占用资源,就一般设置其两倍大小30个

函数型接口和判定型接口

新时代的程序员:lambda表达式、链式编程、函数式接口、Stream流式计算

只有一个方法的接口

四大函数式接口
Function:函数式接口,有一个输入参数,有一个输出
只要是函数式接口 就可以用lambda表达式简化
Predicate:断定行接口
有一个输入参数,返回值只能是布尔值
Comsumer:消费型接口
只有输入没有返回值
Supplier:供给型接口

Stream流式计算

集合+mysql本质就是存储数据的东西
计算都交给流来操作!

ForkJoin

1.7出来的,并行执行任务,提高效率。
把大任务拆分成小任务,计算完进行汇总

特点:工作窃取(A线程执行到中途,B线程先执行完后去帮助A线程执行来体高效率)

如何使用ForkJoin:
forkjoinPool:通过他来执行
计算任务:forkjoinPool.execute(ForkJoinTask task)

一般计算、forkjoin、并行流

异步回调

理解JMM

Volatile

保证可见性
禁止指令重排
不保证原子性
不加sy或者lock的情况下怎么保证原子性
使用原子类解决

彻底明白单例

破坏单例模式:
单例代码的实现是使用双重检测模式,懒汉式单例

 public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Lazy instance = Lazy.getInstance();
        Constructor<Lazy> declaredConstructor = Lazy.class.getDeclaredConstructor(null);
        declaredConstructor.setAccessible(true);
        Lazy instance1 = declaredConstructor.newInstance();

        System.out.println(instance);
        System.out.println(instance1);
    }

在这里插入图片描述

CAS

ABA问题

原子引用

理解各种锁

公平锁:先来后到
非公平锁:可以插队
可重入锁(递归锁)

自旋锁

不断尝试,直到成功为止

死锁

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值