zoukankan      html  css  js  c++  java
  • 线程的通信-生产者消费者

    当对于一个生产者和一个消费者时

    public static void main(String[] agrs) {
    	Resource res = new Resource();
    	Producer p = new Producer(res);
    	Consumer c = new Consumer(res);
    	
    	Thread t1 = new Thread(p);
    	Thread t2 = new Thread(c);
    	t1.start();
    	t2.start();
    }
    
    class Resource {
    	private String name;
    	private int cont = 1;
    	private boolean flag = false;
    	public synchronized void set(String name) {
    		if(flag) {
    			try{
    				this.wait();
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}
    		}
    		this.name = name + "--" + cont++;
    		System.out.println(Thread.currentThread().getName()+"- producer -"+this.name);
    		flag = true;
    		this.notify();
    	}
    	public synchronized void out() {
    		if(!flag) {
    			try {
    				this.wait();
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}
    		}
    		System.out.println(Thread.currentThread().getName()+"---- consumer ----"+this.name);
    		flag = false;
    		this.notify();
    	}
    }
    
    class Producer implements Runnable {
    	private Resource res;
    	Producer(Resource res) {
    		this.res = res;
    	}
    	public void run() {
    		while(true) {
    			res.set("wares");
    		}
    	}
    }
    
    class Consumer implements Runnable {
    	private Resource res;
    	Consumer(Resource res) {
    		this.res = res;
    	}
    	public void run() {
    		while(true) {
    			res.out();
    		}
    	}
    } 
    

    当对于多个生产者和消费者时###

    public static void main(String[] agrs) {
    		Resource res = new Resource();
    		Producer p = new Producer(res);
    		Consumer c = new Consumer(res);
    		
    		Thread t1 = new Thread(p);
    		Thread t2 = new Thread(p);
    		Thread t3 = new Thread(c);
    		Thread t4 = new Thread(c);
    		
    		t1.start();
    		t2.start();
    		t3.start();
    		t4.start();
    	}
    

    会出现生产一个商品,消费出两个商品,或者生产两个而消费一个

    这是因为if语句只判断一次flag标记,消费者的线程生产完会唤醒本方的另一条生产线程,而不判断flag标记,导致生产两次而消费一次
    

    然后我们可以把if换成while
    原因:让被唤醒的线程再一次的判断

    while(flag) {
    	try{
    		this.wait();
    	} catch (InterruptedException e) {
    		e.printStackTrace();
    	}
    }
    

    但是,新的问题又产生了,线程会全部停止
    原因:线程唤醒往往是唤醒线程池的第一个,所以会唤醒本方的线程,会导致数据错乱,加入while后,会导致全部的线程都在等待。我们应该唤醒的是消费者的线程,所以我们可以用notifyAll,唤醒所有的线程,因为会while会判断flag标记,所以不会唤醒生产者的线程,而是唤醒消费者的线程
    notify,容易出现只唤醒本方线程的情况,导致程序中的所有线程等待

    while(flag) {
    	try{
    		this.wait();
    	} catch (InterruptedException e) {
    		e.printStackTrace();
    	}
    }
    this.name = name + "--" + cont++;
    System.out.println(Thread.currentThread().getName()+"- producer -"+this.name);
    flag = true;
    this.notifyALL();
    

    最后改进

    public class Dealer {
    	public static void main(String[] agrs) {
    		Resource res = new Resource();
    		Producer p = new Producer(res);
    		Consumer c = new Consumer(res);
    		
    		Thread t1 = new Thread(p);
    		Thread t2 = new Thread(p);
    		Thread t3 = new Thread(c);
    		Thread t4 = new Thread(c);
    		
    		t1.start();
    		t2.start();
    		t3.start();
    		t4.start();
    	}
    }
    
    class Resource {
    	private String name;
    	private int cont = 1;
    	private boolean flag = false;
    	public synchronized void set(String name) {
    		while(flag) {
    			try{
    				this.wait();
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}
    		}
    		this.name = name + "--" + cont++;
    		System.out.println(Thread.currentThread().getName()+"- producer -"+this.name);
    		flag = true;
    		this.notifyALL();
    	}
    	public synchronized void out() {
    		while(!flag) {
    			try {
    				this.wait();
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}
    		}
    		System.out.println(Thread.currentThread().getName()+"---- consumer ----"+this.name);
    		flag = false;
    		this.notifyAll();
    	}
    }
    
    class Producer implements Runnable {
    	private Resource res;
    	Producer(Resource res) {
    		this.res = res;
    	}
    	public void run() {
    		while(true) {
    			res.set("wares");
    		}
    	}
    }
    
    class Consumer implements Runnable {
    	private Resource res;
    	Consumer(Resource res) {
    		this.res = res;
    	}
    	public void run() {
    		while(true) {
    			res.out();
    		}
    	}
    } 
    
  • 相关阅读:
    读书笔记——吴军《态度》
    JZYZOJ1237 教授的测试 dfs
    NOI1999 JZYZOJ1289 棋盘分割 dp 方差的数学结论
    [JZYZOJ 1288][洛谷 1005] NOIP2007 矩阵取数 dp 高精度
    POJ 3904 JZYZOJ 1202 Sky Code 莫比乌斯反演 组合数
    POJ2157 Check the difficulty of problems 概率DP
    HDU3853 LOOPS 期望DP 简单
    Codeforces 148D. Bag of mice 概率dp
    POJ3071 Football 概率DP 简单
    HDU4405 Aeroplane chess 飞行棋 期望dp 简单
  • 原文地址:https://www.cnblogs.com/rancvl/p/5466465.html
Copyright © 2011-2022 走看看