Java Learn(十六)
线程的基本操作、线程的同步机制
线程的基本操作
static void yield()
— 用于使得当前线程让出 CPU 的执行权转而去执行其他线程
static void sleep(long millis)
— 用于让当前线程休眠参数指定的毫秒数
static void sleep(long millis , int nanos)
— 用于休眠参数指定的毫秒加上纳秒
void interrupt()
— 用于打断正在睡眠的线程(了解)
int getPriority()
— 用于获取当前线程的优先级
int setPriority()
— 用于设置当前线程的优先级
— 优先级高的线程并不一定先执行,只是获取时间片的机会更多一些而已
void join()
— 用于等待调用的对象代表的线程终止
void join(long millis)
— 用于等待该线程终止的最长时间为参数指定的毫秒
void join(long millis, int nanos)
— 用于等待的时间为参数指定的毫秒加纳秒
void setDaemon(boolean on)
— 用于将线程设置为守护线程
boolean isDaemon()
— 用于判断该线程时候为守护线程
— 当所有非守护线程结束时,守护线程也就随之结束,如:垃圾回收线程
线程的同步机制
基本概念
当多个线程同时访问同一个共享资源时,可能会造成数据的不一致等问题,此时就需要进行线程之间的协调和通信,该机制就叫做线程的同步机制。
解决方案
- 由案例可知:当线程一还没有取款结束时,线程就过来取款会导致数据不一致的问题。
- 解决方案:让线程一取款结束后在执行线程二即可,也就是将线程的并发改成串行即可。
- 建议:串行会导致效率比较低,因此建议能不用则尽量不用。
实现方法
在 Java 语言中使用 synchronized 关键字来保证线程执行的原子性,具体方式如下:
使用同步语句块的方式
synchronized(引用/对象){
编写所有需要锁定的代码块;
}
该用法通常用于锁定具体某一段代码的场合中,尽量减少锁定的范围。
使用同步方法的方式
直接使用 synchronized
关键字修饰整个方法,表示锁定方法的所有代码(常见)
该方法本子上等价于 synchronized(this){}
的方式
实现原理
当启动多个线程后各个线程独立运行,并同时去抢占共享资源,若其中一个线程抢到资源则进行加锁处理,其他线程进入阻塞状态,知道该线程执行完毕所有锁定的代码并释放同步锁后,其他线程才能再次抢占共享资源,抢不到的线程继续阻塞。
只有锁定的代码是被多个线程依次串行执行的,其他地方还是并发执行。
死锁的概念
线程一执行的代码:
void run(){
synchronized(a){ //持有同步锁 a,等待同步锁 b
synchronized(b){}
}
}
线程二执行的代码:
void run(){
synchronized(b){ //持有同步锁 b,等待同步锁 a
synchronized(a){}
}
}
经验分享:
在以后的开发中尽量不要使用同步语句块的嵌套使用,避免死锁的发生。
Object类中的方法
void wait()
— 用于让当前正在执行的线程进入等待状态,直到其他线程调用 notify() 或 notifyAll() 方法为止
void wait(long timeout)
— 让线程进入等待状态,直到其他线程调用上述方法或参数指定的时间到了为止,然后接触阻塞状态
void notify()
— 用于唤醒等待的任意一个线程
void notifyAll()
— 用于唤醒等待的所有线程
评论区