Juc知识整理

byzhj 567 0
温馨提示

此为后端学习第二篇,上一篇为《JVM知识整理》后续会将之前整理的学习笔记上传。

一.java多线程

1.线程的实现

  • 进程:一个虚拟机就是一个进程
  • 线程:一个线程是一个类,由主类进行开启,执行公共的业务逻辑代码。
    • 使用场景:io、网络阻塞和非强制依赖(不需要同步)
    • 创建:Thread实现了runnable接口,两种方式没有本质区别,都要重写run()方法,只是多态的问题
      • 继承thread类:Mythread.start()启动,可用匿名内部类快速实现写法。
      • 实现runnable:传入到Thread(实现类)构造器中然后使用thread1.start()启动。
    • 线程安全问题:同一个对象的同一个实例变量的访问。
      • web开发:servlet是单例的,请求线程访问必须是同步的。(所以尽量使用局部变量,实例变量只能是service层注入或一些工具类注入)
    • 线程类的方法:
      • Thread.currentThread().getname()返回当前调用此代码段的线程名。
      • isAlive():返回是否存活(准备运行)状态
      • Thred.sleep():释放cpu一段时间,终止线程。
      • Thread.yield():立即释放时间片,没什么用,有可能立刻抢回来。
      • getid():唯一标识
      • setpriority():设置优先级,但并不是强制抢占时间片。
    • 终止
      • stop()弃用、暴力终止会出现不可预期错误,对对象破坏不一致对其他线程可见。
      • interrupt():只能打中断符号,需要配合手动抛异常或return退出。
      • interrupted()isinterrupted():判断当前线程是否中断,后者会清除该状态,所以应该在run()方法里判断可退出线程。
      • 注意:sleep()和this.interrupt()只要在一起使用就会抛异常,wait和interrupt()也会抛异常,和join()在一起也会抛异常
    • 暂停和恢复:
      • suspend()和resume():弃用、因为暂停线程并且会锁住资源。

 

2.同步

  • synchronized:对该方法进行加锁,即一个java进程中的线程不能同时调用该方法(从堆取加到栈中)。
    • 原理:检查标记ACC,是一个对象锁,
    • synchronized关键字:给非静态方法使用则默认添加本对象锁,且其他syn方法也无法访问
    • 可重入锁:有对象锁就可以调用其他synchronized方法
    • 代码块sycnchronized{}:可在方法内声明具体需要同步的代码,其他代码可以异步。
    • class对象锁synchronized(class):给静态方法默认使用class锁。
    • 解决死锁
      • 工具:jsp命令查看当前线程号——jstack查看线程状态

 

  • volatile:声明一个变量为强制公共区域取值,否则则会从私有栈中取值。
    • 应用:32位操作系统的double赋值,取最新值
    • 缺点:变量volat i++是非原子的,因此得用synchronized
    • 禁止重排序:对没有依赖关系代码jIT会重排序,但volatile变量不会允许赋值重排到后面。

 

3.通信和线程切换

  • wait/notify通信:原始需要让线程sleep()和轮询while()相当于自旋锁,现在在同步块里定义qi
    • 应用:解决经典生产者消费者问题
    • wait():只能写在同步块lock.wait
      • 作用效果:暂停并释放锁,没有锁就抛异常,并发出通知。
      • wait(long):等锁一段时间,没有自动醒,而且必须有锁
    • notify():唤醒wait等待同一锁的所有队列的其中一个线程。
      • 作用效果:会等当前同步块执行完再放锁。

 

  • 状态
    • 阻塞:等syn对象锁、wait()暂停、sleep()睡觉、
    • runnable:获得锁、sleep()结束、获得notify()、io结束

 

  • join():主线程中调用阻塞自身并开启线程,直到开启线程的销毁
    • 作用:让主线程等子线程
    • 特征:底层调用了wait(),会释放自身锁,别的线程能调用此线程同步方法。sleep不行。

 

  • ThreadLocal:此对象能存储属于线程的私有数据
    • set()原理:往Threadmap中存取数据,key就是Threadlocal对象,值为传入value。
    • 作用:任一包的线程能访问threadmap并且存取数据。
    • InheritableThreadLocal:父线程能访问子线程数据

 

二.concurrent

1.Atomic包

  • 概念:实现一些同步变量的包。

 

  • AtomicInteger(x):构造一个原子变量,相当于变量的syn

 

 

 

2.Locks包

  • ReentrantLock:lock接口
    • lock():获取锁,中间写同步代码块
    • unlock():解锁
    • getwaitqueuethreads():返回此锁相关等待线程数
    • isfair():是否为公平锁,默认非公平

 

  • Condition对象:比wait()通知机制好,具有灵活通知特点
    • await():前提条件也是获得锁,相当于objec的wait()
      • 底层是park方法,执行blocker方法。
    • signal():相当于notify()

 

  • ReadwriteLock:解决读锁排它性的问题
    • readlock().lock():作用是获取读锁后,允许继续获得读锁,但不允许写锁进入。
    • writelock().lock():作用相当于lock的互斥

 

3.concurrent包

  • Callable:用法同runnable,可传泛型有返回值,并且能抛异常。
    • call():

 

 

三.单例模式的多线程

1.饿汉模式

  • 实现:通过初始化静态成员变量立即创建单例,并通过静态方法getInstance()获取
    • 二、使用静态块初始化单例

 

  • 线程安全:不能拥有实例化变量,因为非同步,

 

2.懒汉模式/延迟加载

  • 实现:只初始化引用,通过静态方法getInstance()获取对象时再创建对象new SingleInstance

 

  • 线程安全:有可能初次创建时就进入多个线程,出现多个实例。
    • 解决:syn关键字法会严重降低效率。
    • 双检查锁机制DCL:volatile保证对单例对象指针的共享,缩减syn代码块保证只有一个线程会创建对象。
    • volatile必要性:创建对象禁止重排序。
    • 用静态内部类也可以实现。

 

3.反序列化单例模式实现

  • 实现:使用readresolve()方法返回。

发表评论 取消回复
表情 图片 链接 代码

分享