• 线程通信


    线程间通信的方法:


    经典模型:生产者消费者模式

    1.管程法:

    package threadStudy;
    
    public class ThreadCommunicate {
        public static void main(String[] args) {
            Buffer buffer = new Buffer();
            new Producer(buffer).start();
            new Consumer(buffer).start();
        }
    }
    
    class Producer extends Thread {
        Buffer buffer;
        public Producer(Buffer buffer) {
            this.buffer = buffer;
        }
        @Override
        public void run() {
            for (int i = 0; i < 20; i++) {
                System.out.println("生产的第" + i + "杯奶茶" );
                buffer.add(new MilkTea(i));
            }
            
        }
    }
    
    class Consumer extends Thread {
        Buffer buffer;
        public Consumer(Buffer buffer) {
            this.buffer = buffer;
        }
        @Override
        public void run() {
            for (int i = 0; i < 20; i++) {
                System.out.println("消费的第" + i + "杯奶茶" );
                buffer.pop();
            }
        }
    }
    
    //缓冲区
    class Buffer {
        MilkTea[] milkTea = new MilkTea[10];
        private int count = 0;
    
        public synchronized void add(MilkTea m) {
            //缓冲区满了  停止生产
            if(count==milkTea.length) {
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            milkTea[count] = m;
            count++;
            this.notifyAll();
        }
    
        public synchronized MilkTea pop() {
            //缓冲区无东西  停止消费
            if(count==0) {
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            count--;
            MilkTea temp = milkTea[count];
            this.notifyAll();
            return temp;
        }
    }
    
    class MilkTea {
        int id;
        public MilkTea(int id) {
            this.id = id;
        }
        
    }
    输出:
    生产的第0杯奶茶
    消费的第0杯奶茶
    消费的第1杯奶茶
    生产的第1杯奶茶
    生产的第2杯奶茶
    消费的第2杯奶茶
    生产的第3杯奶茶
    消费的第3杯奶茶
    消费的第4杯奶茶
    生产的第4杯奶茶
    生产的第5杯奶茶
    生产的第6杯奶茶
    生产的第7杯奶茶
    生产的第8杯奶茶
    生产的第9杯奶茶
    生产的第10杯奶茶
    生产的第11杯奶茶
    生产的第12杯奶茶
    生产的第13杯奶茶
    生产的第14杯奶茶
    生产的第15杯奶茶
    消费的第5杯奶茶
    消费的第6杯奶茶
    生产的第16杯奶茶
    消费的第7杯奶茶
    消费的第8杯奶茶
    生产的第17杯奶茶
    消费的第9杯奶茶
    生产的第18杯奶茶
    消费的第10杯奶茶
    生产的第19杯奶茶
    消费的第11杯奶茶
    消费的第12杯奶茶
    消费的第13杯奶茶
    消费的第14杯奶茶
    消费的第15杯奶茶
    消费的第16杯奶茶
    消费的第17杯奶茶
    消费的第18杯奶茶
    消费的第19杯奶茶
    View Code

    2.信号灯法

    package threadStudy;
    
    public class ThreadCommunicate2 {
        public static void main(String[] args) {
            Song song = new Song();
            new Actor(song).start();
            new Audience(song).start();
        }
    }
    
    class Actor extends Thread{
        Song song;
        
        public Actor(Song song) {
            this.song = song;
        }
    
        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {
                if(i%2==0) {
                    song.sing("发如雪");
                }
                else {
                    song.sing("青花瓷");
                }
            }
        }
    }
    
    class Audience extends Thread{
        Song song;
        public Audience(Song song) {
            this.song = song;
        }
        
        
        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {
                song.listen();
            }
            
        }
    }
    
    class Song{
        private String name;
        //true 表示演员已经唱好了  false表示还未唱好 即还不可以挺
        private boolean flag = false;
        
        public synchronized void sing(String name) {
            if(flag) {
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            
            this.name = name;
            System.out.println("周杰伦唱了:"+name);
            this.notifyAll();
            flag = !flag;
        }
        
        public synchronized void listen() {
            if(!flag) {
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            System.out.println("我听了:"+this.name);
            this.notifyAll();
            flag = !flag;
        }
    }
    输出:
    周杰伦唱了:发如雪
    我听了:发如雪
    周杰伦唱了:青花瓷
    我听了:青花瓷
    周杰伦唱了:发如雪
    我听了:发如雪
    周杰伦唱了:青花瓷
    我听了:青花瓷
    周杰伦唱了:发如雪
    我听了:发如雪
    周杰伦唱了:青花瓷
    我听了:青花瓷
    周杰伦唱了:发如雪
    我听了:发如雪
    周杰伦唱了:青花瓷
    我听了:青花瓷
    周杰伦唱了:发如雪
    我听了:发如雪
    周杰伦唱了:青花瓷
    我听了:青花瓷
    View Code
  • 相关阅读:
    利用Azure Backup备份和恢复虚拟机(2)
    不允许保存更改。您所做的更改要求删除并重新创建以下表。您对无法重新创建的表进
    Vi命令
    Vi三种模式详解
    C#从Excel中读取数据为空
    Visual Studio 2012/2010/2008 远程调试
    Beyond Compare 3 设置自动换行
    Text类型的字段进行数据替换
    SQLite 连接两个字符串
    基于虚拟日志压缩的数据同步方案
  • 原文地址:https://www.cnblogs.com/ustc-anmin/p/11012857.html
Copyright © 2020-2023  润新知