线程通信
线程通信指的是多个线程通过相互牵制,相互调度,即线程间的相互作用
涉及的三个方法:
.wait 一旦执行此方法,当前线程就进入到阻塞状态,并释放同步监视器
.notify 执行此方法,就会唤醒被wait的一个线程.如果有多个线程被wait,那么就会先唤醒优先级最高的那个
.notifyAll 执行此方法,会唤醒所有被wait的线程
注意:以上三个方法必须使用在同步代码块或同步方法中
wait():必须在同步代码块中使用
必须是使用同步锁对象调用wait()
wait()调用后,锁会释放
必须要通过其他线程来唤醒
经典案例:生产者/消费者问题
生产者(Productor)将产品放在柜台(Counter),而消费者(Customer)从柜台处取走产品,生产者一次只能生产固定数量的产品(比如:1),这时柜台中不能再放产品,此时生产者应停止生产等待消费者拿走产品,此时生产者唤醒消费者来取走产品,消费者拿走产品后,唤醒生产者,消费者开始等待
/*
柜台 放商品 共享数据
*/
public class Counter {
int num = 0;
/*
生产者生产商品
synchronized修饰的是非静态方法 锁是this 就是counter对象,只有一个
*/
public synchronized void add(){
if (num==0){
num++;
System.out.println("生产者生产商品");
this.notify();//唤醒消费者
}else {
try {
this.wait();// 有商品,生产者等待 释放锁
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/*
消费者取走商品
*/
public synchronized void sub(){
if (num==0){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}else {
num--;
System.out.println("消费者拿走了商品");
this.notify();// 唤醒生产者
}
}
}
/*
生产者线程
*/
public class ProductorThread extends Thread {
Counter c;
public ProductorThread(Counter c) {
this.c = c;
}
@Override
public void run() {
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
c.add();
}
}
}
/*
消费者线程
*/
public class CustomerThread extends Thread {
Counter c;
public CustomerThread(Counter c) {
this.c = c;
}
@Override
public void run() {
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
c.sub();
}
}
}
public class Test {
public static void main(String[] args) {
Counter counter = new Counter();// 柜台 只有一个,是共享数据
ProductorThread p = new ProductorThread(counter);
CustomerThread c = new CustomerThread(counter);
p.start();
c.start();
}
}
执行结果: