一、概念理解
——线程之间的“交流”,也就是通过一定的方法,实现线程的控制!
二、相关的API(应用程序接口)
(1)wait
语法:锁对象.wait();
特点:
1.让当前线程等待,直到其他线程调用了该锁对象的notify或notifyAll方法为止,否则将一直等待;
2.wait的调用,必须在同步的前提下;
3.wait的调用,会导致锁的释放;
4.如果等待结束即被唤醒后,则继续从断点处往下执行!
(2)notify和notifyAll
语法:锁对象.notify()|notifyAll();
特点:
1.notify:唤醒当前锁对象下等待的单个线程,优先级较高的优先唤醒,一样则随机;
notifyAll:唤醒当前锁对象下所有等待的线程
2.notify和notifyAll的调用,必须在同步的前提下
注意:
wait、notify、notifyAll和当前同步代码的锁对象都必须是同一个!否则报异常。
【存在问题的实例】
package ThreadTestDemo;
//演示线程的通信
public class TestCommunication {
public static void main(String[] args) {
WithDraw w1 = new WithDraw();
Thread t1 = new Thread(w1);
t1.setName("小徐");
t1.start();
Thread t2 = new Thread(w1);
t2.setName("小倩");
t2.start();
}
}
class WithDraw implements Runnable{//取钱线程
int money = 10000;
@Override
public void run() {
while(true) {
synchronized (this) {//多个线程只有一个对象w1,可用this
if (money <= 0) {
System.out.println("钱已取完");
break;
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "取了1000,还剩" + (money -= 1000));
}
}
}
}
【加入线程通信后】
package ThreadTestDemo;
//演示线程的通信
public class TestCommunication {
public static void main(String[] args) {
WithDraw w1 = new WithDraw();
Thread t1 = new Thread(w1);
t1.setName("小徐");
t1.start();
Thread t2 = new Thread(w1);
t2.setName("小倩");
t2.start();
}
}
class WithDraw implements Runnable{//取钱线程
int money = 10000;
@Override
public void run() {
while(true) {
synchronized (this) {//多个线程只有一个对象w1,可用this
if (money <= 0) {
System.out.println("钱已取完");
break;
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "取了1000,还剩" + (money -= 1000));
//线程通信部分
//通知对方线程可以取钱了
this.notify();//唤醒正在等待的其他线程
//当前线程等待
try {
this.wait();//本线程等待
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}