juc并发编程

方法引用:

  引用符号::三种引用方式

             对象名已经存在,成员方法已经存在,则可以使用对象名来引用成员方法类名已经存在,

        静态成员方法已经存在,则可以使用类名来引用静态成员方法

        构造器引用

一个进程包含多个线程,至少包含一个

java默认 的线程是两个,一个main线程一个gc线程

线程 :

java不能开启线程,开启线程调用的本地的方法  notive调用底层C++

并发编程的本质:充分利用cpu资源

并发/并行

并发(多线程操作同一个资源) 

  单核CPU,模拟出来多条线程,快速交替

并行(多个人一起行走 )

  多核CPU,多个线程一起执行,线程池

线程有六个状态

  new新生

  runnable运行

  blocked阻塞

  waiting等待死死的等

  time_waiting超时等待

  terminated终止 

lock锁      实现类ReentrantLock可重入锁

  公平锁  先来后到

  非公平锁(默认)可以插队 

synchronized和lock的区别
  
synchronized是关键字 lock是一个类
  synchronized是自动的无法获取锁的状态 lock可以判断是否获取到了锁
  synchronized自动释放锁 lock需要手动释放锁 不然会死锁
  synchronized两个线程如果A得到锁B会等待,A阻塞B会一直等待     lock就不一定因为有 trylock方法   
  synchronized可重入锁,不可以中断,非公平 lock
可重入锁,可以判断锁,非公平和公平
  synchronized适合锁少量的 代码同步问题 lock适合大量的同步代码

synchronized生产者消费者如果用if判断会有虚假唤醒问题,需要用while
lock的wait和notify
  condition(相当于监视器)可以多几个来signal精准的通知和唤醒线程 await signal
8锁现象
  synchronized锁的对象是方法的调用者 ,是谁先拿到 谁先执行 详情见D:\Develop\apache-maven-3.8.6-bin\repository\juc的Demo8_1
  有一个普通方法和两个调用对象的时候详见Demo8_2
  加上static锁的是类详见Demo8_3
  一个静态同步方法锁,一个普通锁详见Demo8_4
lock有一个
newCondition,唤醒对应的线程
集合类不安全:
  list不安全
    1.vector直接就是安全的集合synchronized的效率慢 这个类比list出的都早
    2.collections.synchronizedlist(除了list还有好多)
    3.juc包里有很多比如CopyOnWriteArrayList等等
  set和list一样不过没有vector
    set底层就是,map的key 所以是不能重复的 add方法就是调用put方法
 Map
  加载因子,初始化容量
  并发的map可以用 ConcurrentHasMap

Callable

   可以有返回值

  可以抛出异常

  方法不同  call();

  线程调用方法   new thread().start() 

     由于thread里面需要传一个runnable  但是 callable不对,所以需要一个适配器  futureTask  把callable传进去。然后放到thread里面

   获取返回值有一个get方法,但是有可能会阻塞,所以把它写到最后一行  或者异步通信

  还有就是两个线程调用一个,会有缓存,只执行一遍

CountDownLatch  减法计数器

   .countDown减一

   .await 等待归零 在进行下面你的操作

CyclicBarrier  加法计数器

   .await 够了之后    在进行下面你的操作

Semaphore线程阻塞设置几个  几个可以先走 

    acquire()获取

   release() 释放

ReadWriteLock读写锁/共享锁(读锁)/独占锁(写锁)
  实现类
ReentrantReadWriteLock
   
 readWriteLock.writeLock().lock(); 
1      try{}catch{}
      finally{
readWriteLock.writeLock().unlock();}
阻塞队列blockingQueue  非阻塞队列AbstractQueue   双端队列 Deque   
   队列:FIFO  先进先出    写入: 队列满了 就需要阻塞等待   取:队列是空的话必须阻塞等待生产    
  多线程并发,线程池 常用


方式 抛出异常 不会抛出异常有返回值 阻塞等待 超时等待 
添加 

 add

 offer() put   offer(参数,时间,timeunit)
移除  remove poll()   take  poll(时间,timeunit)
判断队列首部  
element
peek()     


synchronizedQueue同步队列    put   take
线程池(重点)三大方法、七大参数、四种拒绝策略
最好不用
Executors而是用ThreadPoolExecutor

   好处:降低资源的消耗,提高响应的速度,方便管理  ------>线程复用,可以控制最大并发数,管理线程

       线程池需要用线程池启动线程   .execute  线程池需要关闭的  .shutdown  放在finally里面

三大方法:

    newSingleThreadExecutor   创建单一的线程

   newFixedThreadPool()  规定线程个数  
newCachedThreadPool 缓存线程 遇强则强
七大参数:最大承载线程,队列加最大核心线程
ThreadPoolExecutor(核心线程大小,最大核心线程大小(cpu密集型(根据电脑来),IO密集型(大于你程序中耗IO的线程)),
            超时了没有人调用就会释放,超时单位,阻塞队列,线程工厂创建线程,拒绝策略)
四种拒绝策略
 
  AbortPolicy超过最大承载就会抛出异常
   CallerRunsPolicy哪来的去哪里,调用线程的人去执行    
DiscardPolicy队列满了不会抛出异常,丢弃任务
     DiscardOldestPolicy尝试和最早的竞争,抛弃最早的进去队列
四大函数式接口:只有一个抽象方法 ,比如runnable
  @FunctionInterface
  function 函数式接口传入T返回R
  Predicate   断定型接口有一个输入参数返回值是布尔类型
  consumer 消费型接口 只要输入没有返回值
  supplier 供给型接口 只有返回值 没有输入
Stream流式计算 
一直.下去 链式编程
ForkJoin
  JDK1.7之后出来,并行执行任务时提高效率,大数据量
  特点:工作窃取 比如两个线程一个执行完了他会偷取另外一个线程的任务,不让线程等待 都是双端队列
想要用的话,需要继承
RecursiveTask<>继承之后就是计算任务,然后fork()方法拆分任务,把任务压入线程队列task1.join+task2.join join方法
需要用线程池去提交任务 newforkJoinPool 然后.submit或者execute submit.get获取结果
详见DemoForkJoin.java
异步回调:future有任务需要一定的时间才能执行完,我们不需要等,可以先去执行其他任务,需要结果的时候再拿过来
  
实现类用CompletableFuture<Void>这是没有返回值的
CompletableFuture.runAsync (上下都是函数式接口用lambda) .get获取结果
                               CompletableFuture.supplyAsync
详见DemoFuture
JMM:java内存模型,不存在的东西,概念 约定
  
volatile是Java虚拟机提供的轻量级的同步机制
  特点:
    1.保证可见性
    2.不保证原子性
    3.禁止指令重排
  约定
    1.线程解锁前,必须把共享变量立刻刷会主存
    2.线程加锁前,必须读取主存中的最新值到工作内存中
    3.加锁和解锁是同一把锁
原子性:Atomic
指令重排,计算机执行程序 源代码-->编译器优化代码重排-->指令并行也可能会重拍-->内存系统也会重拍-->执行
内存屏障在单利模式中使用的最多
单例模式,构造器私有 详见D:\Develop\apache-maven-3.8.6-bin\repository\juc\src\main\java\com\songyue\juc
                 下的DemoSingle
  饿汉式:
  DCL懒汉式:双重检测锁模式

枚举 enum本身是一个类 class-->enum 枚举类型没有无参构造,有一个两个参数的构造方法(string,int)

CAS(自带原子性):ABA问题(你拿到的值其实已经被其他线程修改过了)
  比较当前内存中的值和期望的值,如果这个值是期望的那么久执行操作,否则一直循环
  一次性只能保存一个变量的原子性
AtomicReference原子引用(初始值,版本号).getStamp获取版本号 解决ABA问题
unsafe类
各种锁的理解
  公平锁:非常公平不能插队
  非公平锁:可以插队
  可重入锁:一个锁进入另一个锁

  自旋锁:spinlock详见
MyDemoSpinlock
  死锁:
怎么排查死锁:jps -L(小写)定位进程号 jstack 进程号
日常排查问题:可以看日志 可以看堆栈信息



 

posted @   皇天不负有心人  阅读(24)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示