`
soft901
  • 浏览: 36365 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

生产者/消费者 JAVA

    博客分类:
  • java
阅读更多

   原文:

The producer/Consumer Example

http://life.csu.edu.au/java-tut/essential/threads/synchronization.html

 

    在这个例子中,生产者产生整数0-9存储到Cubblyhole。为了使同步问题更有趣,生产者的生产周期为0-100ms.

 

Cubblehole.java

public class CubbyHole {
	private int contents;
	private boolean available = false;
	
	public synchronized int get(int who) {
		while (!available) {
			try {
				wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		
		available = false;
		System.out.format("Consumer %d got: %d%n", who, contents);
		notifyAll();
		return contents;
	}
	
	public synchronized void put(int who, int value) {
		while (available) {
			try {
				wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		contents = value;
        available = true;
        System.out.format("Producer %d put: %d%n", who, contents);
        notifyAll();
	}
}

 

生产者 Producer.java

public class Producer extends Thread {
	private CubbyHole cubbyhole;

	private int number;

	public Producer(CubbyHole c, int number) {
		cubbyhole = c;
		this.number = number;
	}

	public void run() {
		for (int i = 0; i < 10; i++) {
			cubbyhole.put(number, i);
			try {
				sleep((int) (Math.random() * 100));
			} catch (InterruptedException e) {
			}
		}
	}
}

 

 

当CubbyHole可以消费时,消费者消费CubbyHole中的整数。

 

消费者 Consumer.java

public class Consumer extends Thread {
	private CubbyHole cubbyhole;

	private int number;

	public Consumer(CubbyHole c, int number) {
		cubbyhole = c;
		this.number = number;
	}

	public void run() {
		int value = 0;
		for (int i = 0; i < 10; i++) {
			value = cubbyhole.get(number);
		}
	}
}
 

生产者和消费者共享CubbyHole对象的数据。理想上消费者一个个取得生产者生产的值,但是无论怎么样努力都不能保证这种正确数据。假定这种情况,这两个线程都没有同步;我们讨论可能会发生的潜在的错误。

 

第一个是,生产者的速度比消费者快,连续产生两个数字,使消费者没有取到第一个数字。这种情况下,消费者丢失了一个数字。如下图。

 

Consumer misses number.

 

另一个是,消费者的速度比生产者快,两次消费了同一个值。如下图。

 

 

Consumer gets the same number twice.

 

不管怎么样,这个结果是错误的,是因为消费者应该得到每一个生产者生产的数。这种情况称为竞态条件。竞态是两个或两个以上线程或者进程读或写同一个数据,处理结果依赖于线程执行时间的安排。竞态条件会产生不可预知的结果和细小的程序错误。竞态条件在这个实例中通过同步生产者存储数值到CubbyHole和消费者从CubbyHole取得数值。这种同步行为必须从两个方面同步。

第一,这两个线程不能同时使用CubbyHole。线程可能通过锁一个对象来阻止另一个线程访问。当然一个线程锁了一个对象,另一个线程尝试调用同一个对象的同步方法。第二个线程将会被阻塞直接第一个线程解锁。

第二,这两个线程必须有简单的沟通。沟通的方法是,生产者必须有方法指示消费者,产品已经生产好,等待消费,消费也必须有方法指示生产者,产品已经消费完。java对象已经提供一些方法--wait, notify, and notifyAll -- 帮助线程以特定的条件等待和通知其它线程条件已经改变。

 

 

 

  • 大小: 2.6 KB
  • 大小: 2.7 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics