• 《Java多线程编程核心技术》读后感(八)


     

     

     

     

    不使用等待/通知机制实现线程间通信

    使用sleep()结合while(true)死循环来实现多个线程间通信

    package Third;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class MyList {
    
        private List list = new ArrayList();
    
        public void add() {
            list.add("高洪岩");
        }
    
        public int size() {
            return list.size();
        }
    
    }
    package Third;
    
    public class ThreadA extends Thread {
    
        private MyList list;
    
        public ThreadA(MyList list) {
            super();
            this.list = list;
        }
    
        @Override
        public void run() {
            try {
                for (int i = 0; i < 10; i++) {
                    list.add();
                    System.out.println("添加了" + (i + 1) + "个元素");
                    Thread.sleep(1000);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
    }
    package Third;
    
    public class ThreadB extends Thread {
    
        private MyList list;
    
        public ThreadB(MyList list) {
            super();
            this.list = list;
        }
    
        @Override
        public void run() {
            try {
                while (true) {
                    if (list.size() == 5) {
                        System.out.println("==5了,线程b要退出了!");
                        throw new InterruptedException();
                    }
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
    }
    package Third;
    
    public class Test {
    
        public static void main(String[] args) {
            MyList service = new MyList();
    
            ThreadA a = new ThreadA(service);
            a.setName("A");
            a.start();
    
            ThreadB b = new ThreadB(service);
            b.setName("B");
            b.start();
    
        }
    
    }

     

    虽然两个线程实现了通信,但有一个弊端是,线程ThreadB.java不停地通过while语轮询机制来检测某一个条件,这样会浪费CPU资源。

    如果轮询的时间间隔小,更浪费cpu资源;如果轮询时间间隔大,有可能会娶不到想要的数据。所以就需要有一种机制来减少CPU的资源浪费,而且还可以实现在多个线程间通信,它就是“”wait/notify“”机制。

    什么是等待/通信机制

    等待/通知机制的实现

    package Third;
    
    public class Test1 {
        public static void main(String[] args) {
            try {
                String newString = new String("");
                newString.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    出现异常的原因是没有“”对象监视器“”,也就是没有同步加锁

    package Third;
    
    public class Test2 {
    
        public static void main(String[] args) {
            try {
                String lock = new String();
                System.out.println("syn上面");
                synchronized (lock) {
                    System.out.println("syn第一行");
                    lock.wait();
                    System.out.println("wait下的代码!");
                }
                System.out.println("syn下面的代码");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
    }

    线程不能永远等待下去,那样程序就停止不前,不继续向下运行了。如何使呈现wait状态的线程继续运行?答案是notify()

    package Third;
    
    public class MyThread1 extends Thread {
        private Object lock;
    
        public MyThread1(Object lock) {
            super();
            this.lock = lock;
        }
    
        @Override
        public void run() {
            try {
                synchronized (lock) {
                    System.out.println("开始      wait time=" + System.currentTimeMillis());
                    lock.wait();
                    System.out.println("结束      wait time=" + System.currentTimeMillis());
                }
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    package Third;
    
    public class MyThread2 extends Thread {
        private Object lock;
    
        public MyThread2(Object lock) {
            super();
            this.lock = lock;
        }
    
        @Override
        public void run() {
            synchronized (lock) {
                System.out.println("开始notify time=" + System.currentTimeMillis());
                lock.notify();
                System.out.println("结束notify time=" + System.currentTimeMillis());
            }
        }
    }
    package Third;
    
    public class MyThread2 extends Thread {
        private Object lock;
    
        public MyThread2(Object lock) {
            super();
            this.lock = lock;
        }
    
        @Override
        public void run() {
            synchronized (lock) {
                System.out.println("开始notify time=" + System.currentTimeMillis());
                lock.notify();
                System.out.println("结束notify time=" + System.currentTimeMillis());
            }
        }
    }

    下面实现前面的size()=5的实验

    package Third;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class MyList {
    
        private static List list = new ArrayList();
    
        public static void add() {
            list.add("anyString");
        }
    
        public static int size() {
            return list.size();
        }
    
    }
    package Third;
    
    public class ThreadA extends Thread {
    
        private Object lock;
    
        public ThreadA(Object lock) {
            super();
            this.lock = lock;
        }
    
        @Override
        public void run() {
            try {
                synchronized (lock) {
                    if (MyList.size() != 5) {
                        System.out.println("wait begin "
                                + System.currentTimeMillis());
                        lock.wait();
                        System.out.println("wait end  "
                                + System.currentTimeMillis());
                    }
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
    }
    package Third;
    
    public class ThreadB extends Thread {
        private Object lock;
    
        public ThreadB(Object lock) {
            super();
            this.lock = lock;
        }
    
        @Override
        public void run() {
            try {
                synchronized (lock) {
                    for (int i = 0; i < 10; i++) {
                        MyList.add();
                        if (MyList.size() == 5) {
                            lock.notify();
                            System.out.println("已发出通知!");
                        }
                        System.out.println("添加了" + (i + 1) + "个元素!");
                        Thread.sleep(1000);
                    }
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
    }
    package Third;
    
    public class Run {
    
        public static void main(String[] args) {
    
            try {
                Object lock = new Object();
    
                ThreadA a = new ThreadA(lock);
                a.start();
    
                Thread.sleep(50);
    
                ThreadB b = new ThreadB(lock);
                b.start();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
        }
    
    }

    日志信息wait end在最后输出,这也说明notify()执行后并不立即释放锁

    方法wait()锁释放与notify()锁不释放

    当方法wait()被执行后,锁被自动释放,但执行完notify()方法,锁却不自动释放

    package Third;
    
    public class Service {
    
        public void testMethod(Object lock) {
            try {
                synchronized (lock) {
                    System.out.println("begin wait()");
                    lock.wait();
                    System.out.println("  end wait()");
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
    }
    package Third;
    
    public class ThreadA extends Thread {
    
        private Object lock;
    
        public ThreadA(Object lock) {
            super();
            this.lock = lock;
        }
    
        @Override
        public void run() {
            Service service = new Service();
            service.testMethod(lock);
        }
    
    }
    package Third;
    
    public class ThreadB extends Thread {
        private Object lock;
    
        public ThreadB(Object lock) {
            super();
            this.lock = lock;
        }
    
        @Override
        public void run() {
            Service service = new Service();
            service.testMethod(lock);
        }
    
    }
    package Third;
    
    public class Test {
    
        public static void main(String[] args) {
    
            Object lock = new Object();
    
            ThreadA a = new ThreadA(lock);
            a.start();
    
            ThreadB b = new ThreadB(lock);
            b.start();
    
        }
    
    }

    下面验证方法notify()被执行后,不释放锁

    package Third;
    
    public class Service {
    
        public void testMethod(Object lock) {
            try {
                synchronized (lock) {
                    System.out.println("begin wait() ThreadName="
                            + Thread.currentThread().getName());
                    lock.wait();
                    System.out.println("  end wait() ThreadName="
                            + Thread.currentThread().getName());
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
        public void synNotifyMethod(Object lock) {
            try {
                synchronized (lock) {
                    System.out.println("begin notify() ThreadName="
                            + Thread.currentThread().getName() + " time="
                            + System.currentTimeMillis());
                    lock.notify();
                    Thread.sleep(5000);
                    System.out.println("  end notify() ThreadName="
                            + Thread.currentThread().getName() + " time="
                            + System.currentTimeMillis());
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
    }
    package Third;
    
    public class ThreadA extends Thread {
        private Object lock;
    
        public ThreadA(Object lock) {
            super();
            this.lock = lock;
        }
    
        @Override
        public void run() {
            Service service = new Service();
            service.testMethod(lock);
        }
    
    }
    package Third;
    
    public class NotifyThread extends Thread {
        private Object lock;
    
        public NotifyThread(Object lock) {
            super();
            this.lock = lock;
        }
    
        @Override
        public void run() {
            Service service = new Service();
            service.synNotifyMethod(lock);
        }
    
    }
    package Third;
    
    public class synNotifyMethodThread extends Thread {
        private Object lock;
    
        public synNotifyMethodThread(Object lock) {
            super();
            this.lock = lock;
        }
    
        @Override
        public void run() {
            Service service = new Service();
            service.synNotifyMethod(lock);
        }
    
    }
    package Third;
    
    public class Test {
    
        public static void main(String[] args) throws InterruptedException {
    
            Object lock = new Object();
    
            ThreadA a = new ThreadA(lock);
            a.start();
    
            NotifyThread notifyThread = new NotifyThread(lock);
            notifyThread.start();
    
            synNotifyMethodThread c = new synNotifyMethodThread(lock);
            c.start();
    
        }
    
    }

  • 相关阅读:
    Mysql数据库快速备份还原-mysqldump
    写给年轻人的交友和人脉建议
    令人担忧的趋势:科技崇拜与人文失落
    高情商的特征
    高情商与朋友圈
    数据库临时表空间设置
    oracle 临时表空间的增删改查
    语言表达能力写作能力决定一个人的发展和未来
    一个人如何从平庸到优秀,再到卓越?
    06.堆排序
  • 原文地址:https://www.cnblogs.com/Michael2397/p/7847464.html
Copyright © 2020-2023  润新知