Java并发编程实例--15.在同步代码块中使用条件

并发编程中有个经典问题: 生产消费者问题。
我们有一个数据缓冲区,一个或多个生产者往其中存入对象,另外一个或多个消费者从中取走。
因此,该数据缓冲区是一个共享数据结构,我们需要对其添加读取同步机制,但是我们还需要一些限制。
如果缓冲区满了,生产者不能继续向其中写入;反过来如果缓冲区空了,消费者也不能继续读取。


对于这种情况,Java提供了wait(),notify()和notifyAll()方法。
一个线程可以在同步代码块中调用wait()方法。如果它在同步块之外调用wait()方法,JVM将抛出IllegalMonitorStateException。
当线程调用wait()方法,JVM将该线程睡眠并且释放控制同步代码块的对象,并允许其他线程去执行。
如果需要再次唤醒该线程,只需要调用notify()或notifyAll()方法。


本例中,你将学习如何使用synchronized关键字和wait(), notify(), and notifyAll()方法去实现生产-消费者问题。


缓冲区类:

EventStorage.java
package com.dylan.thread.ch2.c03.task;

import java.util.Date;
import java.util.LinkedList;
import java.util.List;

/**
 * This class implements an Event storage. Producers will storage
 * events in it and Consumers will process them. An event will
 * be a java.util.Date object
 *
 */
public class EventStorage {
   
	/**
	 * Maximum size of the storage
	 */
	private int maxSize;
	/**
	 * Storage of events
	 */
	private List<Date> storage;
	
	/**
	 * Constructor of the class. Initializes the attributes.
	 */
	public EventStorage(){
		maxSize=10;
		storage=new LinkedList<>();
	}
	
	/**
	 * This method creates and storage an event.
	 */
	public synchronized void set(){
			while (storage.size()==maxSize){
				try {
					wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			storage.add(new Date());
			System.out.printf("Set: %d",storage.size());
			notify();
	}
	
	/**
	 * This method delete the first event of the storage.
	 */
	public synchronized void get(){
			while (storage.size()==0){
				try {
					wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			System.out.printf("Get: %d: %s",storage.size(),((LinkedList<?>)storage).poll());
			notify();
	}
	
}

生产者:

Producer.java

package com.dylan.thread.ch2.c03.task;

/**
 * This class implements a producer of events.
 *
 */
public class Producer implements Runnable {

	/**
	 * Store to work with
	 */
	private EventStorage storage;
	
	/**
	 * Constructor of the class. Initialize the storage.
	 * @param storage The store to work with
	 */
	public Producer(EventStorage storage){
		this.storage=storage;
	}
	
	/**
	 * Core method of the producer. Generates 100 events.
	 */
	@Override
	public void run() {
		for (int i=0; i<100; i++){
			storage.set();
		}
	}
}

消费者:

Consumer.java

package com.dylan.thread.ch2.c03.task;

/**
 * This class implements a consumer of events.
 *
 */
public class Consumer implements Runnable {

	/**
	 * Store to work with
	 */
	private EventStorage storage;
	
	/**
	 * Constructor of the class. Initialize the storage
	 * @param storage The store to work with
	 */
	public Consumer(EventStorage storage){
		this.storage=storage;
	}
	
	/**
	 * Core method for the consumer. Consume 100 events
	 */
	@Override
	public void run() {
		for (int i=0; i<100; i++){
			storage.get();
		}
	}

}

主类:

Main.java

package com.dylan.thread.ch2.c03.core;


import com.dylan.thread.ch2.c03.task.Consumer;
import com.dylan.thread.ch2.c03.task.EventStorage;
import com.dylan.thread.ch2.c03.task.Producer;

/**
 * Main class of the example
 */
public class Main {

	/**
	 * Main method of the example
	 */
	public static void main(String[] args) {
		
		// Creates an event storage
		EventStorage storage=new EventStorage();
		
		// Creates a Producer and a Thread to run it
		Producer producer=new Producer(storage);
		Thread thread1=new Thread(producer);

		// Creates a Consumer and a Thread to run it
		Consumer consumer=new Consumer(storage);
		Thread thread2=new Thread(consumer);
		
		// Starts the thread
		thread2.start();
		thread1.start();
	}

}


运行结果:

Set: 1 
Set: 2 
Set: 3 
Set: 4 
Set: 5 
Set: 6 
Set: 7 
Set: 8 
Set: 9 
Set: 10 
Get: 10: Fri May 11 22:31:02 GMT+08:00 2018 
Get: 9: Fri May 11 22:31:02 GMT+08:00 2018 
Get: 8: Fri May 11 22:31:02 GMT+08:00 2018 
Get: 7: Fri May 11 22:31:02 GMT+08:00 2018 
Get: 6: Fri May 11 22:31:02 GMT+08:00 2018 
Get: 5: Fri May 11 22:31:02 GMT+08:00 2018 
Get: 4: Fri May 11 22:31:02 GMT+08:00 2018 
Get: 3: Fri May 11 22:31:02 GMT+08:00 2018 
Get: 2: Fri May 11 22:31:02 GMT+08:00 2018 
Get: 1: Fri May 11 22:31:02 GMT+08:00 2018 
Set: 1 
Set: 2 

...



猜你喜欢

转载自blog.csdn.net/indexman/article/details/80287314
今日推荐