加入公园中有五个门,都有计票器来统计从这个门进入公园的游客数,而控制中心有一个计数器用来统计进入公园的总游客数,这个需求如何实现呢?
1、总计数器---分析可知,总计数器是一个公共资源,需要同步
package CrossDoor;
import java.util.Random;
/**
* @program: MultiThread
* @description: 公园的总计数器
* @author: Miller.FAN
* @create: 2019-10-21 09:36
**/
public class Count {
private int count = 0;
private Random rand = new Random(47);
public synchronized int increment() {
int temp = count;
if(rand.nextBoolean()) {
Thread.yield();
}
return (count = ++temp);
}
public synchronized int value() {
return count;
}
}
2、任务类
package CrossDoor;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* @program: MultiThread
* @description: 进入景区的统计任务
* @author: Miller.FAN
* @create: 2019-10-21 09:40
**/
public class Entrance implements Runnable{
private static Count count = new Count();
private static List<Entrance> entrances = new ArrayList<>();
private int number = 0;
private final int id;
private static volatile boolean canceled = false;
public static void cancel() {
canceled = true;
}
public Entrance(int id) {
this.id = id;
entrances.add(this);
}
/**
* When an object implementing interface <code>Runnable</code> is used
* to create a thread, starting the thread causes the object's
* <code>run</code> method to be called in that separately executing
* thread.
* <p>
* The general contract of the method <code>run</code> is that it may
* take any action whatsoever.
*
* @see Thread#run()
*/
@Override
public void run() {
while(!canceled) {
synchronized (this) {
++ number;
}
System.out.println(this + "Total: " + count.increment());
try {
TimeUnit.MILLISECONDS.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("sleep interrupted!");
}
}
System.out.println("Stopping " + this);
}
public synchronized int getValue() {
return number;
}
public String toString() {
return "Entrance " + id +" : " + getValue();
}
public static int getTotalCount() {
return count.value();
}
public static int sumEntrances() {
int sum = 0;
for(Entrance entrance : entrances) {
sum += entrance.getValue();
}
return sum;
}
}
3、线程池驱动和管理任务
package CrossDoor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/**
* @program: MultiThread
* @description: 统计公园的人流量
* @author: Miller.FAN
* @create: 2019-10-21 09:35
**/
public class CountCrossDoor {
public static void main(String[] args) throws Exception{
ExecutorService exec = Executors.newCachedThreadPool();
for(int i =0; i<5; i++)
exec.execute(new Entrance(i));
//main线程睡眠3秒后给Entrance对象发送cancel消息,然后ExecutorService.shutdown()
TimeUnit.SECONDS.sleep(3);
Entrance.cancel();
exec.shutdown();
if(!exec.awaitTermination(250, TimeUnit.MILLISECONDS))
System.out.println("some tasks were not terminated!");
System.out.println("Total:" + Entrance.getTotalCount());
System.out.println("sum of Entrance:" + Entrance.sumEntrances());
}
}