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;
            }
        }
    
    
    }
     
  • 相关阅读:
    6-Python爬虫-分布式爬虫/Redis
    ES 查询时 排序报错(fielddata is disabled on text fileds by default ... )解决方法
    Intellij Idea webstorm 激活
    Intellij Idea 配置jdk
    java 获取(格式化)日期格式
    js 跳转 XSS漏洞 预防
    CSS去掉背景颜色
    js对象无法当成参数传递 解决方法
    Elasticsearch java api
    java多条件查询SQL语句拼接的小技巧
  • 原文地址:https://www.cnblogs.com/clamp7724/p/11649719.html
Copyright © 2011-2022 走看看