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