美文网首页java架构(停更)
Java多线程notify()和wait()

Java多线程notify()和wait()

作者: CTO_zej | 来源:发表于2017-03-24 23:37 被阅读0次

    基本10家公司面试,7家都会考多线程~~我们直接看下面的代码↓↓↓↓

     public class WaitNotifyOne {
        private volatile static List<String> list = new ArrayList<>();
    
        public void add() {
            list.add("hello,world");
        }
    
        public int size() {
            return list.size();
        }
    
        public static void main(String[] args) {
            final WaitNotifyOne waitNotify01 = new WaitNotifyOne();
            Thread thread1 = new Thread(new Runnable() {
                public void run() {
                    try {
                        for (int i = 0; i < 10; i++) {
                            waitNotify01.add();
                            System.out.println("当前线程:" + Thread.currentThread().getName() + "添加了一个元素..");
                            Thread.sleep(500);
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }, "t1");
            Thread thread2 = new Thread(new Runnable() {
                public void run() {
                    while (true) {
                        if (waitNotify01.size() == 5) {
                            System.out.println(Thread.currentThread().getName() + "收到通知..");
                            System.out.println(Thread.currentThread().getName() + "退出..");
                            break;
                        }
                    }
                }
            }, "t2");
            thread2.start();
            thread1.start();
        }
    }
    

    从代码看很简单,就是thread2先启动线程,然后死循环判断size的大小,如果是5就输出打印,然后thread1就是循环加元素.下面是打印结果↓↓↓↓↓

    当前线程:t1添加了一个元素..
    当前线程:t1添加了一个元素..
    当前线程:t1添加了一个元素..
    当前线程:t1添加了一个元素..
    当前线程:t1添加了一个元素..
    t2收到通知..
    t2退出..
    当前线程:t1添加了一个元素..
    当前线程:t1添加了一个元素..
    当前线程:t1添加了一个元素..
    当前线程:t1添加了一个元素..
    当前线程:t1添加了一个元素..


    从上面的代码来看,thread2是读了一个死循环,这在程序中是很占用资源的,于是有了notify()和wait(),上代码~~

    public class WaitNotifyTwo {
        private volatile static List<String> list = new ArrayList<>();
    
        public void add() {
            list.add("hello,world");
        }
    
        public int size() {
            return list.size();
        }
    
        public static void main(String[] args) {
    
            final WaitNotifyTwo waitNotifyTwo = new WaitNotifyTwo();
    
            final Object object = new Object();
    
            Thread thread1 = new Thread(new Runnable() {
                public void run() {
                    synchronized (object) {
                        try {
                            for (int i = 0; i < 10; i++) {
                                waitNotifyTwo.add();
                                System.out.println("当前线程:" + Thread.currentThread().getName() + "添加了一个元素..");
                                Thread.sleep(500);
                                if (waitNotifyTwo.size() == 5) {
                                    System.out.println(Thread.currentThread().getName() + "发起通知..");
                                    object.notify();
                                }
    
                            }
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }, "t1");
    
            Thread thread2 = new Thread(new Runnable() {
                public void run() {
                    synchronized (object) {
                        if (waitNotifyTwo.size() != 5) {
                            try {
                                System.out.println(Thread.currentThread().getName() + "等待中..");
                                object.wait();
                                System.out.println(Thread.currentThread().getName() + "收到通知..");
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            System.out.println("当前线程:" + Thread.currentThread().getName() + "收到通知线程停止..");
                            throw new RuntimeException();
                        }
                    }
                }
            }, "t2");
            thread2.start();
            thread1.start();
        }
    }
    

    首先理论知识,notify()和wait()方法一般要结合synchronized去使用,wait()方法释放锁,线程堵塞(即不继续执行),而notify()不释放锁,既然不释放锁了,所以肯定继续执行. notify()表示通知唤起,唤起的对象和wait()的对象必须是同一个才有效,如果还不懂啥意思百度~

    然后我们看上面的代码,分析一下,首先thread2开启(为什么一定要thread2先开,自己动脑子),thread2获得object对象的锁,判断长度大小不是5,所以最开始打印的是-->t2等待中,然后调用wait()方法进行堵塞,并且释放锁.thread1获得object对象锁,输出打印-->t1添加了一个元素..当size()等于5的时候,打印-->t1发起通知,,但是notify()不释放锁,所以会继续打印thread1添加了一个元素,,当thread1线程执行结束,thread2 输出 -->t2收到通知 ,t2收到通知线程停止,,,,

    看下面的打印结果↓↓↓↓↓

    t2等待中..
    当前线程:t1添加了一个元素..
    当前线程:t1添加了一个元素..
    当前线程:t1添加了一个元素..
    当前线程:t1添加了一个元素..
    当前线程:t1添加了一个元素..
    t1发起通知..
    当前线程:t1添加了一个元素..
    当前线程:t1添加了一个元素..
    当前线程:t1添加了一个元素..
    当前线程:t1添加了一个元素..
    当前线程:t1添加了一个元素..
    t2收到通知..
    当前线程:t2收到通知线程停止..

    看,就像分析的,就是这么简单!!!!!!!!!!!!!


    看了上面的,我们会发现,第二种方案不能像第一种一样可以做到实时通知,如果用第一种我们cpu的负荷会很大,于是就有了下面优化版的,使用的是java.util.concurrent类,此类之强大,@#$%^&*()_()&%$,佩服万分~~~

    上代码~~

    public class WaitNotifyThree {
        private volatile static List<String> list = new ArrayList<>();
    
        public void add() {
            list.add("hello,world");
        }
    
        public int size() {
            return list.size();
        }
    
        public static void main(String[] args) {
    
            final WaitNotifyThree waitNotifyThree = new WaitNotifyThree();
    
            final CountDownLatch countDownLatch = new CountDownLatch(1);
    
            Thread thread1 = new Thread(new Runnable() {
                public void run() {
                    try {
                        for (int i = 0; i < 10; i++) {
                            waitNotifyThree.add();
                            System.out.println("当前线程:" + Thread.currentThread().getName() + "添加了一个元素..");
                            Thread.sleep(500);
                            if (waitNotifyThree.size() == 5) {
                                System.out.println(Thread.currentThread().getName() + "发起通知..");
                                countDownLatch.countDown();
                            }
    
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }, "t1");
    
            Thread thread2 = new Thread(new Runnable() {
                public void run() {
                    if (waitNotifyThree.size() != 5) {
                        try {
                            System.out.println(Thread.currentThread().getName() + "等待中..");
                            countDownLatch.await();
                            System.out.println(Thread.currentThread().getName() + "收到通知..");
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println(Thread.currentThread().getName() + "收到通知线程停止..");
                    }
                }
            }, "t2");
    
            thread2.start();
            thread1.start();
        }
    }
    

    然后运行结果↓↓↓↓↓↓↓↓↓↓↓↓将来讲~~~~~~~

    t2等待中..
    当前线程:t1添加了一个元素..
    当前线程:t1添加了一个元素..
    当前线程:t1添加了一个元素..
    当前线程:t1添加了一个元素..
    当前线程:t1添加了一个元素..
    t1发起通知..
    当前线程:t1添加了一个元素..
    t2收到通知..
    t2收到通知线程停止..
    当前线程:t1添加了一个元素..
    当前线程:t1添加了一个元素..
    当前线程:t1添加了一个元素..
    当前线程:t1添加了一个元素..

    有啥不懂的请加qq727865942,微信号 cto_zej,觉得是干货请打赏~~~~~~~~~~

    相关文章

      网友评论

        本文标题:Java多线程notify()和wait()

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