一共有100个盒子,每个盒子中有一定数量的能量,每个线程持有一个盒子,向其他盒子中注入能量,实现能量守恒。
public class EnergySystem {
//能量盒子,能量存储的地方
private final double[] energyBoxes;
private final Object lockObj=new Object();
/**
* @param n 能量盒子的数量
* @param initialEnergy 每个能量盒子初始含有的能量
*/
public EnergySystem(int n,double initialEnergy){
energyBoxes=new double[n];
for(int i=0;i<energyBoxes.length;i++)
energyBoxes[i]=initialEnergy;
}
/**
* 能量转移,从一个盒子到另一个盒子
*/
public void transfer(int from,int to,double amount){
synchronized (lockObj){
while(energyBoxes[from]<amount)
try {
lockObj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.print(Thread.currentThread().getName());
energyBoxes[from]-=amount;
System.out.printf("从%d转移%10.2f单位能量到%d",from,amount,to);
energyBoxes[to]+=amount;
System.out.printf("能量总和:%10.2f%n",getTotalEnergies());
//往其他盒子中加过能量,可能就造成某个等待的线程不需要等待
//因为不知道应该唤醒哪个线程,所以唤醒所有的线程
lockObj.notifyAll();
}
}
/**
* 获取能量世界的能量总和
*/
public double getTotalEnergies(){
double sum=0;
for(double amount:energyBoxes)
sum+=amount;
return sum;
}
/**
* 返回能量盒子的长度
*/
public int getBoxAmount(){
return energyBoxes.length;
}
}
public class EnergyTransferTask implements Runnable{
//共享的能量世界
private EnergySystem energySystem;
//能量转移的源能量盒子下标
private int fromBox;
//单次能量转移最大单元
private double maxAmount;
//最大休眠时间
private int DELAY=10;
public EnergyTransferTask(EnergySystem energySystem,int from,double max){
this.energySystem=energySystem;
this.fromBox=from;
this.maxAmount=max;
}
@Override
public void run() {
try {
while(true){
int toBox=(int)(energySystem.getBoxAmount()* Math.random());
double amount=maxAmount*Math.random();
energySystem.transfer(fromBox,toBox,amount);
Thread.sleep((int)(DELAY*Math.random()));
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class EnergySystemTest {
//将要构建的能量世界中能量盒子数量
public static final int BOX_AMOUNT=100;
//每个盒子初始能量
public static final double INITIAL_ENERGY=1000;
public static void main(String[] args){
EnergySystem eng=new EnergySystem(BOX_AMOUNT,INITIAL_ENERGY);
for(int i=0;i<BOX_AMOUNT;i++){
EnergyTransferTask task=new
EnergyTransferTask(eng,i,INITIAL_ENERGY);
Thread t=new Thread(task,"TransferThread_"+i);
t.start();
}
}
}