线程间的通信:
- 等待唤醒机制 -多个线程在操作同一份数据时,避免对同一变量进行争夺
目的:有效利用资源
重点:对资源占用的判断
TimeWaiting -计时等待
- 使用sleep(long m)方法,线程睡醒进入Runnable/Blocked(阻塞状态)
- 使用wait(long m),毫秒值结束之后,若未被唤醒,则会进入阻塞状态
- 注:notify只会唤醒同一锁对象
- wait与notify必须在同步代码块或者同步方法中使用
- 通过锁对象调用
public class ThreadWaitNotifyAll {
public static void main(String[] args) {
Object obj = new Object();
//匿名内部类创建一个线程
new Thread("消费者线程"){
@Override
public void run() {
//等待唤醒只能有一个线程进行,利用同步机制
synchronized (obj) {
System.out.println("消费者:老板我要买东西,给你2s");
try {
obj.wait(2000); //无限等待,直到被唤醒
System.out.println("消费者:收到了,谢谢老板,我带走了");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
new Thread("消费者1线程"){
@Override
public void run() {
//等待唤醒只能有一个线程进行,利用同步机制
synchronized (obj) {
System.out.println("消费者01:老板我要买东西,给你2s");
try {
obj.wait(2000); //无限等待,直到被唤醒
System.out.println("消费者01:收到了,谢谢老板,我带走了");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
//在创建一个线程
new Thread("老板线程"){
@Override
public void run() {
//上面线程等待5s
System.out.println("老板:谢谢你们的5s钟");
synchronized (obj) {
System.out.println("老板:我做好了,来拿吧");
//会唤醒调度队列队头的进程 obj.notify();
//由于是在同步块内,此刻没锁,唤醒后会再获取锁,获取成功RUNNABLE
// 若没获取到,会重新进入调度队列 entry set,WAITING转为BLOCKED状态
//全部唤醒
obj.notifyAll();
}
}
}.start();
}
}
等待唤醒案例:
- 创建一个线程,告知另一线程需要通信,让其进入WAITING状态(无限等待)
- 创建一个另一线程,唤醒上一线程
- 注:顾客和老板线程必须用同步代码块锁起来,保证有一个在执行
- 同步锁对象必须保证唯一
- 只有锁对象能调用wait()/notify()方法
- 在Object类中
void wait()
在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前,导致当前线程等待。
void notify()
唤醒在此对象监视器上等待的单个线程。
void notifyAll()
唤醒在此对象监视器上等待的所有线程,会继续执行wait之后的方法
public class ThreadState {
public static void main(String[] args) {
Object obj = new Object();
//匿名内部类创建一个线程
new Thread("消费者线程"){
@Override
public void run() {
//等待唤醒只能有一个线程进行,利用同步机制
synchronized (obj) {
System.out.println("消费者:老板我要买东西");
try {
obj.wait(); //无限等待,直到被唤醒
System.out.println("消费者:收到了,谢谢老板,我带走了");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
//在创建一个线程
new Thread("老板线程"){
@Override
public void run() {
//花5秒准备东西
try {
System.out.println("老板:好的,等我五秒钟准备一下");
Thread.sleep(0000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//唤醒一个线程
synchronized (obj) {
System.out.println("老板:我做好了,来拿吧");
obj.notify(); //唤醒上面的线程,执行wait之后的代码,但是该线程还没结束
//下面代码仍然在抢占cpu的执行权,因为唤醒后,当前线程还未解锁
System.out.println("老板:哈哈,骗你的继续等吧");
}
//休息会儿让上面的线程先走
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//上面线程结束
System.out.println("老板:不客气");
}
}.start();
}
}