• Demo


    多线程学习笔记3——多线程的互斥和同步

    线程的互斥

    Producer是生产者线程, Consumer是消费者线程,Buffer是生产者与消费者的共享缓冲区, 必须实现读,写的同步.ProducerConsumerProblem 是演示生0read类,在run()创建了方法中生产6产品放到Buffer中,消费者Consumer创建了2个线程分别消费3个物品.

    • Buffer类中利用available变量实现了生产者生成出物品时可以消费.
      消费方法get()当available为false时,调用方法wait()等待.当available为true时消费,然后后把available改为false并调用notifyAll()唤醒生产者线程.
      生产方法put(),当available为true也就是容器为空时,生产者才可以想buffer中放产品,如果不能放则等待,放好后吧available改为true说明容器中有产品,消费这可以消费了,接着调用notifyAll()唤醒等待的消费者线程.

    其中synchronize同步关键字,当一个线程用这个方法操作的时候,不允许其他线程对这个方法进行操作,从而保持主方法中创建的2个消费者线程保持互斥.

    //生产者线程
    class Producer extends Thread{
        private Buffer buffer;
        private int number;
        public Producer(Buffer buffer, int number){
            this.buffer = buffer;
            this.number = number;
        }
        public void run(){
            for (int i = 0;i < 6;){
                buffer.put(i);
                System.out.println("生产者#"+number+"生产"+(i++));
                try {
                    Thread.sleep((int)(Math.random()*2000));
                }catch (InterruptedException exc){}
            }
        }
    }
    
    //消费者线程
    class Consumer extends Thread{
        private Buffer buffer;
        private int number;
    
        public Consumer (Buffer buffer, int number){
            this.buffer = buffer;
            this.number = number;
        }
        public void run(){
            for (int i=0;i<3;i++){
                int v = buffer.get();
                System.out.println("消费这#"+number+"消费"+v);
            }
        }
    }
    
    //生产者与消费者共享的缓冲区,必须实现读,写的同步
    class Buffer {
        private int contents;
        private boolean available = false;
    
        public synchronized int get() {
            while (!available) {
                try {
                    //wait()会让线程挂起,直到通知到它继续执行!挂起的线程会存放到等待队列中,按照wait的先后顺序存放。
                    this.wait();
                } catch (InterruptedException exc) {
                }
            }
            int value = contents;
            //消费着取出内容,改变存取控制available
            available = false;
            System.out.println("取出" + contents);
            //notify()通知等待队列中的第一个线程,notifyAll()通知的是等待队列中的所有线程
            this.notify();
            return value;
        }
    
        public synchronized void put(int value) {
            while (available) {
                try {
                    this.wait();
                } catch (InterruptedException exc) {
                }
            }
            contents = value;
            //生成这放入内容,改变存取控制
            available = true;
            System.out.println("放入" + contents);
            this.notifyAll();
        }
    }
    
    public class ProducerConsumerProblem {
        public static void main(String[] args) {
            Buffer buffer = new Buffer();
            new Producer(buffer,101).start();
            new Consumer(buffer,200).start();
            new Consumer(buffer,201).start();
        }
    }
    

    所以访问共享资源的方法都必须是synchronize的,否则程序肯定会出错.

    线程的同步

  • 相关阅读:
    12-认识容量和升(四上)
    11 认识1-5(一上)
    10 圆柱的表面积(六下)
    009 单式折线统计图(五下)
    008 解决问题的策略 转化(苏教版 五下)
    007 分数的基本性质(五下)
    006 三位数乘两位数(四上)
    kafka,MQ消息队列
    005 圆的周长(六上)
    004 平行四边形的面积(五上)
  • 原文地址:https://www.cnblogs.com/kongw/p/13893396.html
Copyright © 2020-2023  润新知