zoukankan      html  css  js  c++  java
  • Java生产者与消费者(下)


                                          本文来自http://blog.csdn.net/liuxian13183/ ,引用必须注明出处!


    上一讲我们让消费者和生产者都各停1毫秒,实际上大多并不是这样的。第二讲,我们讲一个极端的例子和一个正常的例子,假设您已经看过上一讲,我们只改变Consumer和Producer,来看结果。

    Java生产者与消费者(上)

    名词解释

    wait:当前线程不运行,处理等待状态,等待notify;所以也不会往下执行。

    您可能会有疑问前例中的为什么要用while循环而非if语句?

    主要是防止多线程操作时,例桌子已经占满,两个生产线程均处理等待状态,但消费线程通过notifyAll打开其等待状态,就造成生产过量的蛋糕,而导致生产消费模式失败,所以不能用if语句。

    sleep:暂停当前线程若干时间,之后继续运行

    Special Sample:生产者和消费者均不加sleep

    Result:

    Produce1 produce:1
    Produce2 produce:2
    Produce1 produce:3
    Produce1 produce:4
    Produce1 produce:5
    Produce1 begin to wait !
    Consumer1 consume:5
    Consumer1 consume:4
    Consumer1 consume:3
    Consumer1 consume:2
    Consumer1 consume:1
    Consumer1 begin to wait !
    Produce1 stop waiting !
    Produce1 produce:1
    Produce1 produce:2
    Produce2 produce:3
    Produce2 produce:4
    Produce2 produce:5
    Produce2 begin to wait !
    Consumer2 consume:5
    Consumer2 consume:4
    Consumer2 consume:3
    Consumer2 consume:2
    Consumer2 consume:1
    Consumer2 begin to wait !
    Produce2 stop waiting !
    Produce2 produce:1
    Produce2 produce:2
    Produce2 produce:3
    Produce2 produce:4
    Produce2 produce:5
    Produce2 begin to wait !
    Produce1 begin to wait !
    Consumer1 stop waiting !
    Consumer1 consume:5
    Consumer1 consume:4
    Consumer1 consume:3
    Consumer1 consume:2
    Consumer1 consume:1
    Consumer1 begin to wait !
    Produce1 stop waiting !
    Produce1 produce:1
    Produce1 produce:2
    Produce1 produce:3
    Produce1 produce:4
    Produce1 produce:5
    Produce1 begin to wait !
    Produce2 stop waiting !
    Produce2 begin to wait !
    Consumer2 stop waiting !
    Consumer2 consume:5
    Consumer2 consume:4
    Consumer2 consume:3
    Consumer2 consume:2
    Consumer2 consume:1
    Consumer2 begin to wait !
    Produce2 stop waiting !
    Produce2 produce:1
    Produce2 produce:2
    Produce2 produce:3
    Produce2 produce:4
    Produce2 produce:5
    Produce2 begin to wait !
    Produce1 stop waiting !
    Produce1 begin to wait !
    Consumer1 stop waiting !
    Consumer1 consume:5
    Consumer1 consume:4
    Consumer1 consume:3
    Consumer1 consume:2
    Consumer1 consume:1
    Consumer1 begin to wait !
    Produce1 stop waiting !
    Produce1 produce:1
    Produce1 stop at last !
    解析:例子很极端,生产和消费均两个线程,A线程在工作时B在等待;

    A生产线程生产,B生产线程等待直到A生产完;

    A消费线程消费,B消费线程等待直到A消费完;

    B生产线程生产,A生产线程等待直到A生产完;
    B消费线程消费,A消费线程等待直到A消费完;

    ……

    这样一个循环,失去多线程的意义所在(变成了单线程)!

    正常的例子:生产可能只需要1毫秒,消费需要2毫秒

    Produce1 produce:1
    Consumer1 consume:1
    Consumer2 begin to wait !//此时Consumer2检测到count为0,所以等待
    Produce2 produce:1
    Consumer2 stop waiting !//此时Consumer2检测到count已经大于0,所以打开
    Consumer2 consume:1
    Produce1 produce:1//看,生产与消费是无序的。两者分开,不管你在不在生产,我都要消费,只要蛋糕还有;
    Produce2 produce:2//不管你消费不消费,只要桌子还有空的;它们两个均对一种情况负责:桌子和蛋糕形成的映射关系!
    Consumer2 consume:2
    Consumer1 consume:1
    Produce2 produce:1
    Produce1 produce:2
    Produce2 produce:3
    Produce1 produce:4
    Consumer1 consume:4
    Consumer2 consume:3
    Produce1 produce:3
    Produce2 produce:4
    Produce2 produce:5
    Produce1 begin to wait !
    Consumer1 consume:5
    Produce1 stop waiting !
    Produce1 produce:5
    Produce2 begin to wait !
    Consumer2 consume:5
    Produce2 stop waiting !
    Produce2 produce:5
    Produce2 begin to wait !
    Produce1 begin to wait !
    Consumer2 consume:5
    Produce1 stop waiting !
    Produce1 produce:5
    Produce2 stop waiting !
    Produce2 begin to wait !
    Consumer1 consume:5
    Produce2 stop waiting !
    Produce2 produce:5
    Produce1 begin to wait !
    Produce2 begin to wait !
    Consumer1 consume:5
    Consumer1 stop at last !
    解析:这次我让执行25次即退出虚拟机。

    大家可以看到,本次两个生产线程和两个消费线程,在生产和消费的时候都是无序的,无论你要不要停,我都要工作,不能让一个线程一直抓住锁不放,其实这才是多线程本质。

    代码如下:

    Producer:

    public class Producer extends Thread {
    	Table table;
    	String threadName;
    
    	public Producer(String string, Table table) {
    		// TODO Auto-generated constructor stub
    		this.table = table;
    		this.threadName = string;
    		this.setName(threadName);
    	}
    
    	@Override
    	public void run() {
    		// TODO Auto-generated method stub
    		super.run();
    		try {
    			while (true) {
    				table.produce(threadName);
    				sleep(1);
    			}
    		} catch (InterruptedException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    	}
    }
    

    消费者:

    public class Consumer extends Thread {
    	Table table;
    	String threadName;
    
    	public Consumer(String string, Table table) {
    		// TODO Auto-generated constructor stub
    		this.table = table;
    		this.threadName = string;
    		this.setName(threadName);
    	}
    
    	@Override
    	public void run() {
    		// TODO Auto-generated method stub
    		super.run();
    		try {
    			while (true) {
    				table.consume(threadName);
    				sleep(2);
    			}
    		} catch (InterruptedException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    	}
    }
    








  • 相关阅读:
    在安卓上用Termux安装sqlmap
    地址转换函数
    字节操作函数
    主机字节序和网络字节序
    20191231 Spring官方文档(Core 1.13-1.14)
    20191230 Spring官方文档(Core 1.12)
    20191230 Tomcat权威指南-读书摘要系列【归档】
    20191230 On Java8【归档】
    20191227 Java8 日期时间API
    20191226 Spring官方文档(Core 1.11)
  • 原文地址:https://www.cnblogs.com/hehehaha/p/6147358.html
Copyright © 2011-2022 走看看