• 浅谈多线程并发


    一句话总结:

                通过wait 、notify、synchronized锁、flag标记位来实现线程的交替执行

    核心代码:

                synchronized (s) 
                {
                    if (s.flag)
                    s.wait();
                    //自定义操作
                    s.flag = true;
                    s.notify();
                }

    -------------------------------------------------------对上课内容的总结如下-------------------------------------------------------

    代码目的:实现女孩线程和男孩线程交替问问题

    一、两个线程仅加锁的情况,会出现一个线程重复抢占资源

    package cn.sgy.io.system;
    
    public class WaitNotifyDemo {
    
        public static void main(String[] args) {
    
            Student s = new Student();
            s.setName("Tom");
            s.setGender('男');
    
            new Thread(new Ask(s)).start();
            new Thread(new Change(s)).start();
    
        }
    
    }
    
    class Change implements Runnable {
    
        private Student s;
    
        public Change(Student s) {
            this.s = s;
        }
    
        public void run() {
    
            while (true) {
                synchronized (s){if (s.getGender() == '男') {
                    s.setName("Amy");
                    s.setGender('女');
                } else {
                    s.setName("Tom");
                    s.setGender('男');
                }
    
                }
            }
    
        }
    }
    
        
        
        class Ask implements Runnable {
    
            private Student s;
    
            public Ask(Student s) {
                this.s = s;
            }
    
            @Override
            public void run() {
    
                while (true) {
    
                   synchronized (s) {
                        
                    System.out.println("我是" + s.getName() + ",我是" + s.getGender());
                    System.out.println("请教了一个问题~~~");
    
                    }
                }
            }
    
        }
    
    class Student {
    
        private String name;
        private char gender;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public char getGender() {
            return gender;
        }
    
        public void setGender(char gender) {
            this.gender = gender;
        }
    }

    二、两个线程加锁内加Thread.sleep,结果无济于事只会让程序变慢(sleep不会打破锁机制)

    package cn.sgy.io.system;
    
    public class WaitNotifyDemo {
    
        public static void main(String[] args) {
    
            Student s = new Student();
            s.setName("Tom");
            s.setGender('男');
    
            new Thread(new Ask(s)).start();
            new Thread(new Change(s)).start();
    
        }
    
    }
    
    class Change implements Runnable {
    
        private Student s;
    
        public Change(Student s) {
            this.s = s;
        }
    
        public void run() {
    
            while (true) {
                synchronized (s) {
                    
    
                if (s.getGender() == '男') {
                    s.setName("Amy");
                    s.setGender('女');
                } else {
                    s.setName("Tom");
                    s.setGender('男');
                }
                
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
    
                }
            }
    
        }
    }
    
        
        
        class Ask implements Runnable {
    
            private Student s;
    
            public Ask(Student s) {
                this.s = s;
            }
    
            @Override
            public void run() {
    
                while (true) {
    
                    synchronized (s) {
                        
                    System.out.println("我是" + s.getName() + ",我是" + s.getGender());
                    System.out.println("请教了一个问题~~~");
    
                    }
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
    
        }
    
    class Student {
    
        private String name;
        private char gender;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public char getGender() {
            return gender;
        }
    
        public void setGender(char gender) {
            this.gender = gender;
        }
    }

    三、在锁内加入等待唤醒机制,结果两个线程都在等待没有任何输出

    package cn.sgy.io.system;
    
    public class WaitNotifyDemo {
    
        public static void main(String[] args) {
    
            Student s = new Student();
            s.setName("Tom");
            s.setGender('男');
    
            new Thread(new Ask(s)).start();
            new Thread(new Change(s)).start();
    
        }
    
    }
    
    class Change implements Runnable {
    
        private Student s;
    
        public Change(Student s) {
            this.s = s;
        }
    
        public void run() {
    
            while (true) {
                synchronized (s) {
                    
    
                   try {
                        s.wait();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }if (s.getGender() == '男') {
                    s.setName("Amy");
                    s.setGender('女');
                } else {
                    s.setName("Tom");
                    s.setGender('男');
                }
                
                s.notify();
                }
    
                }
            }
    
        }
    
    
        
        
        class Ask implements Runnable {
    
            private Student s;
    
            public Ask(Student s) {
                this.s = s;
            }
    
            @Override
            public void run() {
    
                while (true) {
    
                    synchronized (s) {
                        try {
                            s.wait();
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    System.out.println("我是" + s.getName() + ",我是" + s.getGender());
                    System.out.println("请教了一个问题~~~");
    
                    }
                    s.notify();
                    }
                }
            }
    
        
    
    class Student {
    
        private String name;
        private char gender;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public char getGender() {
            return gender;
        }
    
        public void setGender(char gender) {
            this.gender = gender;
        }
    }

    四、加入标记位(flag=true -> Ask线程     flag=false -> Change线程)

     

    package cn.sgy.io.system;
    
    public class WaitNotifyDemo {
    
        public static void main(String[] args) {
    
            Student s = new Student();
            s.setName("Tom");
            s.setGender('男');
    
            new Thread(new Ask(s)).start();
            new Thread(new Change(s)).start();
    
        }
    
    }
    
    class Change implements Runnable {
    
        private Student s;
    
        public Change(Student s) {
            this.s = s;
        }
    
        public void run() {
    
            while (true) {
                synchronized (s) {
                    
                    if(s.flag == true)
    
                    try {
                        s.wait();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                if (s.getGender() == '男') {
                    s.setName("Amy");
                    s.setGender('女');
                } else {
                    s.setName("Tom");
                    s.setGender('男');
                }
                s.flag=true;
                
                s.notify();
                }
    
                }
            }
    
        }
    
    
        
        
        class Ask implements Runnable {
    
            private Student s;
    
            public Ask(Student s) {
                this.s = s;
            }
    
            @Override
            public void run() {
    
                while (true) {
    
                    synchronized (s) {
                        
                        if(s.flag == false)try {
                            s.wait();
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    System.out.println("我是" + s.getName() + ",我是" + s.getGender());
                    System.out.println("请教了一个问题~~~");
    
                    s.flag = false;
                    
                    s.notify();
                    }
                    
                    }
                }
            }
    
        
    
    class Student {
    
        private String name;
        private char gender;
    
        public boolean flag = true;
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public char getGender() {
            return gender;
        }
    
        public void setGender(char gender) {
            this.gender = gender;
        }
    }

    五、每个线程类对应了两个线程后出现问题

    package cn.tedu.thread;
    
    public class WaitNotifyAllDemo {
    
        public static void main(String[] args) {
    
            Student s = new Student();
            s.setName("Tom");
            s.setGender('男');
    
            new Thread(new Ask2(s)).start();
            new Thread(new Ask2(s)).start();
            new Thread(new Change2(s)).start();
            new Thread(new Change2(s)).start();
        }
    
    }
    
    class Change2 implements Runnable {
    
        private Student s;
    
        public Change2(Student s) {
            this.s = s;
        }
    
        @Override
        public void run() {
    
            while (true) {
    
                synchronized (s) {
    
                    while (s.flag)
                        try {
                            s.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
    
                    if (s.getGender() == '男') {
                        s.setName("Amy");
                        s.setGender('女');
                    } else {
                        s.setName("Tom");
                        s.setGender('男');
                    }
    
                    s.flag = true;
    
                    // 唤醒在等待的线程
     s.notify();
    
                }
    
            }
    
        }
    
    }
    
    class Ask2 implements Runnable {
    
        private Student s;
    
        public Ask2(Student s) {
            this.s = s;
        }
    
        @Override
        public void run() {
    
            while (true) {
                synchronized (s) {
    
                    while (!s.flag)
                        try {
                            s.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
    
                    System.out.println("我是" + s.getName() + ",我是" + s.getGender());
                    System.out.println("请教了一个问题~~~");
    
                    s.flag = false;
    
                    s.notify();
                }
            }
    
        }
    
    }

    六、出现问题的原因

    知识基础:线程在等待期间是在这个锁所对应的线程池(队列)中等待

    一句话总结:A执行完,应该释放C时却把排在C前面的A释放,导致C无法执行

    解释:A1为 Ask线程   A2为Ask2线程   两者为同一操作  

             C1为Change线程 C2位Change2线程   两者为同一操作

    因为队列只能先进先出,所以释放的时候都是释放最先进入的元素,所以当遇到且仅遇到以下两种情况时会出现全部进入线程池的情况

            

    当C程序执行结束,而C线程再一次抢到资源的时候,因为交替执行需要的A线程,所以把抢到资源的C1和C2都放入了线程池中,这时才轮到A2线程来执行A程序

    

    七、使用 s.notifyAll()解决问题

    notifyAll用于释放线程池中的所有等待的线程,因为使得代码整洁才使用这种低效率的方法

    package cn.tedu.thread;
    
    public class WaitNotifyAllDemo {
    
        public static void main(String[] args) {
    
            Student s = new Student();
            s.setName("Tom");
            s.setGender('男');
    
            new Thread(new Ask2(s)).start();
            new Thread(new Ask2(s)).start();
            new Thread(new Change2(s)).start();
            new Thread(new Change2(s)).start();
        }
    
    }
    
    class Change2 implements Runnable {
    
        private Student s;
    
        public Change2(Student s) {
            this.s = s;
        }
    
        @Override
        public void run() {
    
            while (true) {
    
                synchronized (s) {
    
                    while (s.flag)
                        try {
                            s.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
    
                    if (s.getGender() == '男') {
                        s.setName("Amy");
                        s.setGender('女');
                    } else {
                        s.setName("Tom");
                        s.setGender('男');
                    }
    
                    s.flag = true;
    
                    // 唤醒在等待的线程
     s.notifyAll();
    
                }
    
            }
    
        }
    
    }
    
    class Ask2 implements Runnable {
    
        private Student s;
    
        public Ask2(Student s) {
            this.s = s;
        }
    
        @Override
        public void run() {
    
            while (true) {
                synchronized (s) {
    
                    while (!s.flag)
                        try {
                            s.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
    
                    System.out.println("我是" + s.getName() + ",我是" + s.getGender());
                    System.out.println("请教了一个问题~~~");
    
                    s.flag = false;
    
                    s.notifyAll();
                }
            }
    
        }
    
    }

    -------------------------------------------------------谢谢观看,如有问题还请指正-------------------------------------------------------

  • 相关阅读:
    Team饭来了团队作业3需求改进与系统设计
    2016012006崔啸寒 散列函数的应用及其安全性
    结对项目之四则运算
    《构建之法》第四章,第十七章所感
    2016012006小学四则运算练习软件项目报告
    读《构建之法》之一,二,十六章有感
    追梦软件路,愿不忘初心
    信息安全作业5 有关散列函数安全性的知识扩展
    结对作业:四则运算网页版
    Week4-作业1:阅读笔记与思考
  • 原文地址:https://www.cnblogs.com/songyao2018/p/8407843.html
Copyright © 2020-2023  润新知