所有对象都自动含有单一的锁,当一个线程在对象上调用其任意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方法中去掉任意一个,就会有打印异常发生,并终止运行。有兴趣的可以试试。