等待/通知机制
等待/通知的相关方法是任意Java对象都具备的,因为这些方法被定义在所有对象的超类 java.lang.Object上,方法如下:
1.notify:通知一个在对象上等待的线程,使其从main()方法返回,而返回的前提是该线程获取到了对象的锁。
2.notifyAll:通知所有在等待该对象的线程。
3.wait():调用该方法的线程进入WAITING状态,只有等待其他线程的通知或者被中断,才会返回。需要注意调用wait方法后,会释放对象的锁。
private Object object = new Object();
public static void main(String[] args) throws InterruptedException {
new test01().print();
}
public void print() throws InterruptedException {
new Thread(() -> {
synchronized (object) {
System.out.printf(Thread.currentThread().getName(), "1111");
try {
/**
* wait()释放锁资源 同时会阻塞线程
* wait()、notify()结合synchronized
*/
object.wait();
} catch (Exception e) {
e.printStackTrace();
}
System.out.printf(Thread.currentThread().getName(), "0001");
}
}).start();
try {
Thread.sleep(3000);
synchronized (object) {
object.notify();
}
} catch (Exception e) {
e.printStackTrace();
}
}
通过wait、notity实现生产者和消费者模型
可以协调生产者和消费者的速度差异,不需要强制二者速率一致。
/**
* 共享对象
*/
class Gao {
public String name;
private char sex;
/**
* flag false 默认false
* false 输入线程输出值 输出线程拿到锁释放锁
* true 输出线程输出值 输入线程拿到锁释放锁
*/
public Boolean flag = false;
}
/**
* 输入线程
*/
class InputThread extends Thread {
private Gao gao;
public InputThread(Gao gao) {
this.gao = gao;
}
@Override
public void run() {
int count = 0;
while (true) {
//线程安全 给共享全局对象上锁
synchronized (gao) {
//如果gao.flag==true 输入的资源主动释放锁
if(gao.flag){
try {
gao.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (count == 0) {
gao.name = "高";
gao.sex = '男';
} else {
gao.name = "gao";
gao.sex = '女';
}
gao.flag = true;
//唤醒阻塞线程
gao.notify();
}
count = (count + 1) % 2;
}
}
}
/**
* 输出线程
*/
class OutputThread extends Thread {
private Gao gao;
public OutputThread(Gao gao) {
this.gao = gao;
}
@Override
public void run() {
while (true) {
synchronized (gao) {
//线程安全 给共享全局对象上锁 出现情况:输出线程会一直拿到锁对象,没有释放
//解决方法 wait() 如果 gao.flag==false 输出的资源主动释放锁
if(!gao.flag){
try{
gao.wait();
}catch (Exception e){
}
}
System.out.println(gao.name + "," + gao.sex);
gao.flag = false;
gao.notify();
}
}
}
}
public static void main(String[] args) {
new Thread01().print();
}
public void print() {
//全局对象
Gao gao = new Gao();
//输入线程
InputThread inputThread = new InputThread(gao);
//输出线程
OutputThread outputThread = new OutputThread(gao);
inputThread.start();
outputThread.start();
}