多线程——死锁、同步、通信
多线程之常用方法
start();
//启动当前线程,调用当前线程的run();
run();
//通常需要重写Thread类中的此方法,将创建的线程要执行的操作声明在此方法中;
currentThread();
//静态方法,返回执行当前代码的线程。
getName();
//获取当前线程的名字
setName();
//设置当前线程的名字
yield();
//释放当前cpu的执行权
join();
//在线程a中调用线程b的join(),此时线程a就进入阻塞状态,直到线程b完全执行结束。
sleep(long time);
//让当前线程"睡眠"指定的time毫秒
多线程之同步
在Java中,我们通过同步机制来解决线程的安全问题。
方法一:同步代码块
synchronized(同步监视器){
//需要被同步的代码
}
说明:
-
操作共享数据的代码,即为需要被同步的代码。
-
共享数据:多个线程共同操作的变量。
-
同步监视器,俗称:锁。任何一个类的对象,都可以充当锁。
要求:多个线程必须要共用一把锁。
- 同步的方式,解决了线程的安全问题。(优点)
- 操作同步代码时,只能有一个线程参与,其他线程等待。(局限性)
方法二:同步方法
public class synchronized void show(){
//需要被同步的代码
}
说明:
-
同步方法仍然涉及到同步监视器,只是不需要我们显示声明。
-
非静态的同步方法,它的同步监视器是:this
静态的同步方法,它的同步监视器是:当前类本身
死锁
不同的线程分别占用对方需要的同步资源不放弃,都在等待对方放弃自己需要的同步资源,就形成了线程的死锁。
说明:
- 出现死锁后,不会出现异常,不会出现提示,只是所有的线程都处于阻塞状态,无法继续。
- 我们使用同步时,要避免出现死锁。
-
synchronized与lock的异同
相同:二者都可以解决线程安全问题
不同:synchronized机制在执行完相应的同步代码后,自动释放同步监视器。
lock需要手动地启动同步 lock() ,同时结束同步也可以手动实现。
优先使用顺序:lock -> synchronized(){} -> class synchronized
多线程之通信
多线程通信案例:交替打印
针对 synchronized涉及到三个方法:
wait();
//一旦执行此方法,当前线程就进入阻塞状态,并释放同步监视器。
notify();
//一旦执行此方法,就会唤醒被wait的一个线程,如果有多个线程被wait,就优先唤醒优先级高的。
norifyAll();
//一旦执行此方法,就会唤醒所有被wait的线程。
Q:sleep和wait的异同?
A:
-
相同点 一旦执行该方法,当前线程都将进入阻塞状态。
-
不同点 1.两个方法声明的位置。(Thread/Object)
2.使用场景。(anywhere/synchronized)
3.同时出现时,sleep不会释放同步监视器,wait会。