美文网首页
Java并发之wait、notify、notifyAll详解

Java并发之wait、notify、notifyAll详解

作者: 吾乃零陵上将军邢道荣是也 | 来源:发表于2021-06-15 18:39 被阅读0次
    线程状态转换图.png

    问题:请使用两个线程一个线程用来打印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();
        }
    }
    

    总结

    1. wait()、notify/notifyAll() 方法是Object的本地final方法,无法被重写。
    2. 一般在synchronized同步代码块里使用wait()、notify()和notifyAll()方法。
    3. 当线程执行wait()方法时,会释放当前的锁,然后让出CPU,进入等待队列。(所以使用wait()的前提的先获得锁)
    4. 当线程t执行notify或notifyAll()方法后,会唤醒一个或全部正处于等待状态的线程,但是线程t不会立即释放锁,直到执行完同步代码块的代码或者遇到wait()方法,才会释放锁。所以被唤醒的锁也不会立即获得锁。
    5. wait() 需要被try catch包围,以便发生异常中断也可以使wait等待的线程唤醒。
    6. notify唤醒沉睡的线程后,线程会接着上次的执行继续往下执行。
    7. 永远在循环里调用wait()和notify(),而不是在if语句。
    8. notify方法只唤醒一个等待线程。notifyAll 会唤醒所有等待线程,尽管哪一个线程将会第一个处理取决于操作系统。

    相关文章

      网友评论

          本文标题:Java并发之wait、notify、notifyAll详解

          本文链接:https://www.haomeiwen.com/subject/mhgzeltx.html