美文网首页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