多线程详解

1 多线程

1.1 实现多线程方式

继承多线程和实现Runnable接口。

1.2 启动线程

start(),run()只是调用方法;start()重复调用将会抛出异常

1.3 停止线程

1.3.1 正确停止线程

停止线程 interrupt()
获取停止线程信号

  • interrupted() currentThread().isInterrupted(true);重置
  • isInterrupted() isInterrupted(false)不重置
    传递中断:处理中断的最好方法是将中断异常抛出,传递到顶层,让run函数处理
    恢复中断:Thread.currentThread().interrupt()

1.3.2 错误的停止方法

  • stop() 会导致程序处于一种无法预估的状态,这与编程的思想相违背

  • suspend() 和锁一起挂起,容易导致死锁

  • resume() suspend()的逆操作

  • voletile和flag方式,其实和中断类似,但是遇到sleep等阻塞操作时,程序变锁死了,而Interrupt却可以响应所有存在阻塞的操作。

1.3.3 如何分析native方法

  • 进github或者openJDK网站

1.3.4

对于不能响应的InterruptException的阻塞,没有通用解决方案,有时需要用到具体类的方法响应。

1.4 线程的生命周期

在这里插入图片描述

2 Thread与Object重要方法

2.1 wait/notify/notifyAll

  • 必须先拥有monitor
  • 只能唤醒一个线程
  • 属于Object类

2.2 JRE JDK JVM

JRE : 包含JVM,和其他类库,运行时环境,用于运行环境
JDK : 包含JRE,开发工具包
JVM :虚拟机

2.3 sleep

不占用CPU资源
不释放锁synchronized,lock
如果休眠期间被中断,则抛出InterruptedException

2.4 join

  • 等待其他线程执行完成,再出发;主线程等待主线程 otherThread.join()
  • 源码中包含wait(),线程执行完毕后会有notifyAll

2.5 yield

  • 释放CPU时间片、不释放锁、不进入阻塞状态
  • JVM不保证遵循
  • 与sleep区别在于,可以被再次调度

2.6 线程的各个属性

  • 线程Id 从1自增,JVM首先会创建很多线程
  • 线程名字
  • 用户线程与守护线程 守护线程用于给用户线程提供服务;由JVM启动;不影响JVM退出
  • 线程优先级,1-10;默认5;程序不应该依赖优先级

2.7 UncaughtExceptionHandler

  • 主线程可以轻松发现异常,子线程却不行
  • 无法在主线程中用try...catch捕获子线程异常
    解决方案:
  • 在每个run方法里加入try...catch捕获语句,缺点是太繁杂了
  • 利用UncaughtExceptionHandler
    • 程序统一设置Thread.setDefaultUncaughtExceptionHandler()
    • 单个线程设置
    • 线程池设置

3 线程安全

3.1 对象发布和初始化时候的安全问题

  • 方法返回一个只读private对象 使用复本
  • 未初始化完成就提供给外界
    • 构造函数中还未初始化完成就用this赋值
    • 隐式逸出-注册监听事件
    • 构造函数中使用多线程

4 死锁

当两个或多个线程(进程)相互持有对方所需要的资源,又不主动释放。导致程序都陷入阻塞

4.1 四个必要条件

  • 互斥
  • 请求与保持
  • 不可剥夺
  • 循环等待

4.2 检查死锁

  • jstack
    • jps java查看进程pid
    • jstack pid 查看是否有死锁
  • ThreadMXBean.findDeadlockedThreads()

4.3 修复死锁策略

  • 避免策略 :通过调整获取锁的顺序来破除循环等待条件,当条件相等时引入额外的锁。
  • 哲学家就餐问题:
    • 服务员检查:提前问服务员是否可以就餐(避免策略)
    • 改变拿筷子的顺序(避免策略)
    • 餐票(避免策略)
    • 领导调节(检测与恢复)

4.4 避免死锁

  • 设置超时时间 lock.trylock()
  • 多使用并发类而不是自己设计锁
  • 降低锁的粒度
  • 使用同步代码块而不是同步方法:自己指定锁对象
  • 给线程起有意义的名字
  • 避免锁的嵌套
  • 分配资源前先计算能不能回收:银行家算法
  • 尽量不要几个功能使用同一把锁:专锁专用

4.5 其他活跃性故障

4.5.1 活锁

线程没有阻塞,也始终在运行,但是得不到进展,做重复的事情。
引入随机性解决

4.5.2 饥饿

当线程需要某些资源,但永远得不到

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值