问题:请使用两个线程一个线程用来打印1-26,另一个线程依次打印A-Z,要求交叉打印。
//1.使用wait和notify方法
public class WaitAndNotify {
static Thread t1=null,t2=null;
private static volatile boolean t1HasPrint=false;//标记信号量
public static void main(String[] args) {
Object lock=new Object();
t1=new Thread(()->{
for (char i='A';i<='Z';i++){
synchronized (lock){
while (t1HasPrint){
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.print(i);
t1HasPrint=true;
lock.notify();
}
}
},"t1");
t2=new Thread(()->{
for (int i=1;i<=26;i++){
synchronized (lock){
while (!t1HasPrint){
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.print(i);
t1HasPrint=false;
lock.notify();
}
}
},"t2");
t2.start();
t1.start();
}
}
//2.使用LockSupport
public class TestLockSupport {
static Thread t1=null,t2=null;
private static volatile boolean t1HasPrint=false;
public static void main(String[] args) {
t1=new Thread(()->{
for (char i='A';i<='Z';i++){
while (t1HasPrint){
LockSupport.park();
}
System.out.print(i);
t1HasPrint=true;
LockSupport.unpark(t2);
}
},"t1");
t2=new Thread(()->{
for (int i=1;i<=26;i++){
while (!t1HasPrint){
LockSupport.park();
}
System.out.print(i);
t1HasPrint=false;
LockSupport.unpark(t1);
}
},"t2");
t2.start();
t1.start();
}
}
总结:
- wait()、notify/notifyAll() 方法是Object的本地final方法,无法被重写。
- 一般在synchronized同步代码块里使用wait()、notify()和notifyAll()方法。
- 当线程执行wait()方法时,会释放当前的锁,然后让出CPU,进入等待队列。(所以使用wait()的前提的先获得锁)
- 当线程t执行notify或notifyAll()方法后,会唤醒一个或全部正处于等待状态的线程,但是线程t不会立即释放锁,直到执行完同步代码块的代码或者遇到wait()方法,才会释放锁。所以被唤醒的锁也不会立即获得锁。
- wait() 需要被try catch包围,以便发生异常中断也可以使wait等待的线程唤醒。
- notify唤醒沉睡的线程后,线程会接着上次的执行继续往下执行。
- 永远在循环里调用wait()和notify(),而不是在if语句。
- notify方法只唤醒一个等待线程。notifyAll 会唤醒所有等待线程,尽管哪一个线程将会第一个处理取决于操作系统。
网友评论