仿真任务
装饰花园
在这个仿真程序中花园委员会想统计每天通过多个门,进入花园的人数,每个门上有个十字转门相当于是计数器。转动任意一扇门就表示公园的分享计数值就会增加一。
代码如下:
计数器:
/**
* 计数器
*
*/
public class Counter {
private int value;
private Random random = new Random(47);
public synchronized int increment() {
if (random.nextBoolean())
Thread.yield();// 给个机会让它切换线程
return ++value;
}
public synchronized int getValue() {
return value;
}
}
入口:
public class Entrance implements Runnable {
private static Counter counter = new Counter();
private static ArrayList<Entrance> stores = new ArrayList<>();
private int num;
private final int id;
private static volatile boolean canceled = false;
public Entrance(int id) {
super();
this.id = id;
stores.add(this);
}
@Override
public void run() {
// TODO Auto-generated method stub
while (!canceled) {
synchronized (this) {
++num;
}
System.out.println(this + " total:" + counter.increment());
try {
TimeUnit.MILLISECONDS.sleep(300);// 模拟一下 不要一直 递增
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("stop:("+id+") num:"+num);
}
@Override
public synchronized String toString() {
return "Entrance (" + id + ") num:" + num;
}
public static int getTotal() {
return counter.getValue();
}
public static int sum() {
int sums = 0;
for (Entrance e : stores) {
sums += e.num;
}
return sums;
}
public static void cancel() {
canceled = true;
/**
* 看过一些资料说对原始类型不包括(long,double)变量进行赋值是原子操作
* d对引用变量的赋值操作是否是原子操作见:https://www.zhihu.com/question/46681046 第二个回答
*
*/
}
}
花园仿真类:
public class Garden {
public static void main(String[] args) {
ExecutorService exec = Executors.newCachedThreadPool();
for (int a = 0; a < 5; a++) {
exec.execute(new Entrance(a));
}
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Entrance.cancel();
exec.shutdown();
boolean flag = false;
try {
flag = exec.awaitTermination(2000, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (!flag)
System.out.println("some task don't over.");
System.out.println("total:" + Entrance.getTotal());
System.out.println(" sums:" + Entrance.sum());
}
}
运行结果:
可以删除上面的程序中的 任意 同步代码块 的 同步修饰 就可以看到程序运行失败的效果。
程序中 exec.awaitTermination(2000, TimeUnit.MILLISECONDS); 这个方法的意思 是 executorService 在指定的时间中任务全部停止完毕的话 会返回true。否则返回false.