好久不见!
线程
概念
线程是进程的组成部分,它代表了一条顺序的执行流
优缺点
多线程优点
性能高,效率高
多线程缺点
线程多了之后,线程本身的调度也是一个麻烦事儿,需要消耗较多的CPU
创建线程
三种方式
继承Thread,重写run方法 + start开启线程
实现Runnable接口,重写run方法 + start开启线程
实现Callable接口,重写call方法 + 线程池
三种方式优点
第一种
- 编写简单,如果需要访问当前线程,则无须使用Thread.currentThread()方法,直接使用this即可获得当前线程
第二种
- 接口多实现,类的单继承
- 实现资源共享
第三种
- call方法可以抛出异常,可以定义返回值,run方法不可以
三种方式缺点
第一种
- 因为线程类已经继承了Thread类,所以不能再继承其他父类
第二种第三种
- 编程稍稍复杂,如果需要访问当前线程,则必须使用Thread.currentThread()方法
线程状态
新建状态(new)
就绪状态(Runnable)
如何进入就绪
- 1.start()
- 2.阻塞解除
- 3.cpu的调度切换
- 4.yield 礼让线程
• 当线程执行到yield方法,会让出cpu的资源,同时线程会恢复就绪状态
运行状态(Running)
阻塞状态(Blocked)
进入阻塞状态状态后,阻塞解除后,不能直接恢复到运行,会直接恢复高就绪状态,等待cpu的调度
如何让线程进入阻塞状态
- 1.sleep()
- 2.join() 插队线程
• A线程执行过程中,如果B线程插队了,A线程就会进入到阻塞状态,等待插队线程执行完毕|等待执行的时间,A线程会恢复到就绪状态
- 3.wait() 等待
- 4.IO
终止状态(Dead)
一旦进入终止状态不可恢复
如何进入终止状态
- 1.正常执行完毕
- 2.stop() 过时--> 不推荐使用
- 3.通过标识判断
线程安全
概念
当多个线程同时操作同一份资源,才有可能出现线程不安全问题
线程安全
同步方法
- 同步实例方法
• 调用成员方法的对象
• 整个方法体
- 同步静态方法
• 锁类->锁的类的Class对象->一个类只有一个,加载到内存中究存在Class对象,不变,唯一
• 整个方法体
同步块
- 类名.class
• 锁类相当于锁住了这个类的所有对象,如果只想要锁当前类的某一个对象,建议锁那一个具体的对象this
- this
• 锁类相当于锁住了这个类的所有对象,如果只想要锁当前类的某一个对象,建议锁那一个具体的对象this
- 资源
• 锁对象,锁不变的内容
线程通信
注意
- wait()
• 等待,通过对象调用wait()方法让当前进入等待阻塞状态,会进入到调用wait方法对象的等待池中进行等待,等待被唤醒让出cpu的资源,同时释放对象的锁
- notify()
• 唤醒 : 唤醒对象等待池中正在等待的线程,被唤醒的线程进入到就绪队列,需要被cpu调度同时获取对象锁才能执行
- notifyAll
• 唤醒全部
注意
- wait()与notify()必须使用在同步环境下,用来协调多线程对共享数据存储的问题,否则会抛出异常 IllegalMonitorStateException
- 如果当前线程不是此对象监视器的所有者。
线程通信
线程安全
同步方法
- 同步实例方法
• 调用成员方法的对象
• 整个方法体
- 同步静态方法
• 锁类->锁的类的Class对象->一个类只有一个,加载到内存中究存在Class对象,不变,唯一
• 整个方法体
同步块
- 类名.class
• 锁类相当于锁住了这个类的所有对象,如果只想要锁当前类的某一个对象,建议锁那一个具体的对象this
- this
• 锁类相当于锁住了这个类的所有对象,如果只想要锁当前类的某一个对象,建议锁那一个具体的对象this
- 资源
• 锁对象,锁不变的内容
线程通信
注意
- wait()
• 等待,通过对象调用wait()方法让当前进入等待阻塞状态,会进入到调用wait方法对象的等待池中进行等待,等待被唤醒让出cpu的资源,同时释放对象的锁
- notify()
• 唤醒 : 唤醒对象等待池中正在等待的线程,被唤醒的线程进入到就绪队列,需要被cpu调度同时获取对象锁才能执行
- notifyAll
• 唤醒全部
注意
- wait()与notify()必须使用在同步环境下,用来协调多线程对共享数据存储的问题,否则会抛出异常 IllegalMonitorStateException
- 如果当前线程不是此对象监视器的所有者。