所有对象都自动含有单一的锁,当一个线程在对象上调用其任意synchronzied方法的时候,此对象就会被加锁,这个时候如果调用对象的其他非synchronzied的方法,不受限制;但是其他线程如果想要调用该对象的synchronzied的方法,就需要等待前一个synchronized方法调用完成后释放了锁才能被调用。所以应对所有访问和修改共享资源的方法设置为synchronzied,漏掉一个该方法都有问题。

下面是一个简单的例子。所以定义了一个可以制作两种食物的餐厅类,foodA, foodB所消耗相同食材material的量不同。餐厅自带一个库存监控器,当食材量小于最小库存时,就添加供给。

package com.sooscc.untils.test.thread;

public class Restaurant implements Runnable{
	public final String name;
	private int material= 100;
	protected int MIN_INVENTORY = 5;
	protected int MAX_INVENTORY = 1000;
	private boolean exceptionOcur;	
	private Thread monitor;
	
	public Restaurant(String name,int material) {
		this.name = name;
		this.material = material;
		monitor = new Thread(this);
		monitor.setDaemon(true);
		monitor.start();
	}
	
	public Restaurant(int material){
		this.name = "A Restaurant";
		this.material = material;
		monitor = new Thread(this);
		monitor.setDaemon(true);
		monitor.start();
	}

	public synchronized void productFoodA(){
		if(material>=2){
			System.out.println("Food A is produced by "+name+". Remaining material:"+material);
			material-=2;
			if(material<0)
				setExceptionOcur(true);
		}else{
			System.out.println("Waiting supplyment to produce A");
		}
	}
	
	public synchronized void productFoodB(){
		if(material>=3){
			System.out.println("Food B is produced by "+name+". Remaining material:"+material);
			material-=3;
			if(material<0)
				setExceptionOcur(true);
		}else{
			System.out.println("Waiting supplyment to produce B");
		}
	}
	
	public boolean isExceptionOcur() {
		return exceptionOcur;
	}

	public void setExceptionOcur(boolean exceptionOcur) {
		System.out.println("Exception occur");
		this.exceptionOcur = exceptionOcur;
	}

	
	public synchronized void supply(){
		material= material+2000> MAX_INVENTORY? MAX_INVENTORY : material+2000;
	}
	
	
	public void run() {
		while(true){
			if(material<MIN_INVENTORY){
				supply();
			}
		}		
	}	
}

对该餐馆下达多道生产不同的食物的安排,餐馆自管理库存,要求不能出错。

package com.sooscc.untils.test.thread;

import java.util.concurrent.TimeUnit;

import com.sooscc.untils.test.thread.Arrangement;

public class Arrangement implements Runnable{
	Restaurant restaurant;
	String arrangment;
	Thread t = new Thread(this);
	Arrangement(String preference, Restaurant resta){
		this.arrangment = preference;
		this.restaurant = resta;
		t.start();
	}
	
	public void run(){
		while(!this.restaurant.isExceptionOcur()){
			if("A".equalsIgnoreCase(this.arrangment)){
				this.restaurant.productFoodA();
			}else{
				this.restaurant.productFoodB();
			}
			try {
				TimeUnit.MILLISECONDS.sleep(1);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
	
	public static void main(String[] args) throws Exception{
		Restaurant orangeRestaurant = new Restaurant("Orange", 500);
		for(int i=0;i<5;i++){
			new Arrangement("A", orangeRestaurant);
		}	
		for(int i=0;i<5;i++){
			new Arrangement("B", orangeRestaurant);
		}
	}
}

上面的代码可以保证餐馆一直正常运行下去。 但是如果将synchronzied关键字从Restaurant的synchronzied方法中去掉任意一个,就会有打印异常发生,并终止运行。有兴趣的可以试试。

发表评论