Java 语言进阶 -- 线程

Thread 类常用的 API 方法

  • start(): 线程的启动

  • run():线程的运行(由start()方法自动调用)

  • stop():线程的停止(不建议使用)

  • setPriority():设置线程优先级

  • setName():设置线程的名字

  • isAlive():测试线程是否处于活动状态

通过 Runnable 接口构造线程

Runnable 接口:可以将CPU 代码和数据分开,形成清晰的模型,还可以从其他类继承。

Thread 接口:编写简单,直接继承,重写run方方法,不能再从其他类继承。

多线程的同步控制

线程间的互斥:: 同时运行的几个线程需要共享一些数据,共享的数据,在某一个时刻只允许一个线程访问。

典型的如:生产者/消费者 问题

**synchronize **:线程同步关键字,实现互斥

  • 用于指定需要同步的代码段或方法,也就是监视区

  • 可实现与一个线程的互斥

  • 首先判断对象的锁是否存在,如果在就获得锁,用完再释放锁。

同步与锁的要点

  • 只能同步方法,不能同步变量

  • 每个对象只有一个锁

  • 类可以同时拥有同步和非同步方法,非同步方法不受锁的限制。

  • 线程休眠时,它所持有的任何锁都不会被释放。

  • 线程可以获得多个锁

  • 同步会损害并发性,应该尽可能缩小同步的范围。

  • 需要说明是获取哪个对象的锁

线程的等待与唤醒

wait()方法:线程的等待

notify(): 随机唤醒一个等待的线程

notifyAll(): 唤醒所有等待的线程

后台线程

也叫守护线程,通常是为了辅助其他线程而运行的线程

它不妨碍程序的终止。

使用 setDaemon()设置后台线程。

线程的生命周期与死锁

一个线程在任何一个时刻都处于某个状态中。Java 线程的状态有以下几种:

  • New:新创建的线程,尚未执行;

  • Runnable:运行中的线程,正在执行run()方法的Java代码;

  • Blocked:运行中的线程,因为某些操作被阻塞而挂起;

  • Waiting:运行中的线程,因为某些操作在等待中;

  • Timed Waiting:运行中的线程,因为执行sleep()方法正在计时等待;

  • Terminated:线程已终止,因为run()方法执行完毕。

线程的几种基本状态:诞生、就绪、运行、阻塞、休眠、死亡状态。

死锁: 多个线程互相等待对方释放的资源,此即为死锁。

结束线程的声明:通过控制 run 方法中的循环条件的方式来结束一个线程,不建议使用 stop 方法。

线程的调度

控制多个线程在同一个 CPU 上以某种顺序运行称为线程调度。

每个 java 线程都有一个优先级,其范围在 0-10 之间,默认情况下,每个线程的优先级都设置为 5。

基于优先级的线程调度

  • 对具有同优先级的线程,java 的处理是随机的。

  • 高优先级的线程优先执行。

setPriority() 方法: 设置线程优先级

小结

  • 线程的同步方法

  • 线程的声明周期

  • 线程的优先级

线程安全与线程兼容

java的线程安全

  • 不可变: 如 final 修饰数据、String 类型数据、枚举类型数据、Long、Double

  • 绝对的线程安全:

  • 相对的线程安全:

线程兼容和线程对立

线程对立:无论调用端是否采用了同步措施,都无法保证两个线程的安全运行。

如何实现线程安全

互斥同步: 临界区、互斥量、信号量

synchronized 关键字 :对自己是可重入的,不会把自己锁死。

ReentrantLock 重入锁:性能比 synchronized 更好

非阻塞同步

  • 使用基于冲突检测的乐观并发策略。

  • 使用硬件处理器指令进行不断重试策略(JDK1.5 以后)

无同步方案

  • 可重入代码:也称为纯代码。

  • 线程本地存储。

如何进行锁优化

锁优化源自于 jdk6

自旋锁: 为了让线程等待,让线程进行自旋锁,java 默认是自旋 10 次。

自适应自旋:自旋时间不固定

锁消除:不需要加锁的就进行锁消除

锁粗化: 包含更多的代码

偏向锁:在无竞争的情况下把整个同步都消除掉。

每天学习一点点,每天进步一点点。

posted @ 2020-07-31 16:00  爱吃西瓜的番茄酱  阅读(140)  评论(0编辑  收藏  举报