zoukankan      html  css  js  c++  java
  • java

    https://www.cnblogs.com/clamp7724/p/11648308.html

    在基础中使用了java自带的Vector线程安全处理多线程。

    这次试试用锁来进行处理

    线程锁:

    synchronized

    使用synchronized修饰方法,这样调用这个方法的时候,这个方法会被锁定,只有当前对象使用完后才能释放让其他对象使用。
    不加这个可能会多个对象同时访问这个方法,导致出现线程问题(比如出货方法,A运行到这个方法的判断是否还有货物,判断还有货物,B这时刚好也运行方法拿走了货物,A开始拿货就会报错)

    public synchronized void 方法名(){...}
    或者
    synchronized (需要锁定的对象){ ... } 执行完代码后解锁

    线程控制:
    wait:
    Object.wait() 让执行这个Object的线程进入等待状态,直到cpu再次分配资源(只要线程不消亡或者报错,cpu有空的时候还会自动分配资源给它执行),注意这里操作的对象是线程,多个单线程操作同一个对象,其中一个线程进入等待不影响其它线程操作这个对象。
    如果在某个方法中写this.wait(); 进入等待状态的是当前操作这个对象的线程,不是当前class的对象。比如A调用了B中方法,这个方法有个this.wait(),执行到那里这个线程会断掉(不再继续往下执行),等待唤醒再继续。不影响C去调用B的方法。
    所有线程都进入wait() ---》 假死状态。
    防止假死需要找时机对线程进行唤醒(notify,notifyAll)

    sleep:
    Thread.sleep(等待时间毫秒)。 让调用方法的对象进入等待状态,等待时间到了自动醒来。


    Object.notify:
    唤醒当前对象的其中一个线程(cpu决定优先级,或者提前用 object.setPriority(int 优先级) 设置优先级,优先级为1-10, 10最高)

    Object.notifyAll:
    唤醒对象的所有线程。

    生产消费者模型:
    有人往仓库放,有人从仓库拿,多人同时操作同一个仓库。

    主函数

    package multi_thread;
    
    public class MultiThreadTest {
        public static void main(String[] args) {
            Customer c1 = new Customer("消费者1");
            Customer c2 = new Customer("消费者2");
            Customer c3 = new Customer("消费者3");
            Customer c4 = new Customer("消费者4");
    
            Productor p1 = new Productor("生产者1");
            Productor p2 = new Productor("生产者2");
            //生产者优先级高一些,先生产再消费
            p1.setPriority(10);
            p2.setPriority(10);
    
    
            //初始10个产品,有4个消费者每人买20次,2个生产者每人生产25个,也就是说至少会有20次买不到(消费速度 > 生产速度,还没来得及生产出来也可能买不到)
    
            c1.start();
            c2.start();
            c3.start();
            c4.start();
            p1.start();
            p2.start();
    
    
        }
    }

    消费者

    package multi_thread;
    
    public class Customer extends Thread{ //消费者,买取货物
        private String name;
        public Customer(String name){
            this.name = name;
        }
    
        public void run(){
            for(int i = 0; i < 20; i++) {  //假设每个消费者需要20个产品
                buyGood();
            }
        }
    
        private void buyGood(){
            Goods g = Goods.getInstance();
            String s = g.removeGood();
    
            //多线程锁的另一种写法,在一段代码外面添加synchronized(上锁的对象){}
            //这样可以达到和方法上锁一样的效果
    //        synchronized(g) {
    //            s = g.removeGood();
    //        }
    
            if(s != null){
                System.out.println(name + "买走了" + s);
            }
            else{
                System.out.println(name + "发现没货啦!");
    //            try {
    //                this.sleep(500);  //当前Customer对象等0.1秒再买
    //                System.out.println(name + "又开始买东西了!");
    //            } catch (InterruptedException e) {
    //                e.printStackTrace();
    //            }
                //让某个Thread 对象(c1继承了Thread)等待111毫秒后自动醒来
            }
        }
    }

     

    生产者

    package multi_thread;
    
    public class Productor extends Thread{ //生产者,增加货物
        private String name;
        public Productor(String name){
            this.name = name;
        }
    
        public void run(){
            for(int i = 0; i < 30; i++) {  //假设每个生产者生产30个产品停止,刚好满足消费
                productGood();
            }
        }
    
        private void productGood(){
            Goods g = Goods.getInstance();
            String s = g.addGood();
            System.out.println(name + "生产了" + s);
    
        }
    }

    货物仓库

    package multi_thread;
    
    import java.util.ArrayList;
    
    public class Goods { //货物仓库,这次用String表示货物
    
        private int num = 1; //用来区分货物
        private static Goods goods = new Goods();
        private ArrayList<String> goodList = new ArrayList<>();  //用String代表货物,懒得创建一个新类了。。。
    
        {
            for(int i = 0; i < 20; i++){
                addGood();
            }
        }
        //块,在构造方法之前自动运行,初始添加20个货物
    
        private Goods(){
        }
    
        public static Goods getInstance(){
            return goods;
        }
    
        //生产一个货物
        public synchronized String addGood(){  //使用synchronized锁定方法,这样调用这个方法的时候,Goods对象会被锁定,执行完后才能释放。
    
            goodList.add("货物" + num);
            num++;
            return "货物" + num;//返回生产的货物名字
        }
    
        //消费一个货物
        public synchronized String removeGood(){
            if(goodList.size() > 0) {
                String s = goodList.remove(0);
                return s;//返回消费的货物名字;
            }
            else{
                try {
                    //wait的不是货物的线程,而是当前执行这个方法的对象所在线程(只有消费者调用这个方法)
                    System.out.println("有人发现到货物" + num + "的时候没货啦,等在那里不动啦");
    
                    //没有添加this.notifyAll();的情况下:
                    //发现这句话运行了4遍后,4个消费者都没再买东西(因为消费者消费速度 > 生产者生产速度,还没来得及生产就卖完了),只有2个生产者还在生产。
                    //程序卡在这里不再继续执行,称为:假死状态。
                    //为了防止假死,在这个线程进入等待状态时,唤醒其他线程。
                    //
    
                    //notify
                    this.notifyAll();  //----加上这句后,线程可以正常运行完毕。某个消费者发现没货后,过段时间还会再次尝试过购买(其他消费者发现没货了让他醒了)
                    this.wait();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return null;
            }
        }
    
    
    }
     
  • 相关阅读:
    iOS 新建xib文件时,最外层view的约束问题
    React native 无法弹出调试控件的问题
    从GitHub下载demo时遇到的依赖问题
    Mac 解决 Sourcetree 同步代码总需要密码的问题
    Mac 安装JRE 1.8
    正则表达式-- (.*?) 或 (.*+)
    字符串内有多个#号,每俩#号为一组,JavaScript 截取每组#号之间的字符
    Js/jQuery实时监听input输入框值变化
    Redis设置密码
    redis本机能访问 远程不能访问的问题
  • 原文地址:https://www.cnblogs.com/clamp7724/p/11649719.html
Copyright © 2011-2022 走看看