有一个map,key存储候选人名称,value存储该候选人的得票数。请实现一个线程安全的投票系统.
为了测试并发环境下的表现,我们先设计一个小的“框架”,用来模拟并发情况下的投票行为。 首先设计一个接口,代测试的代码在这个接口的方法里面被调用
public interface Worker {
void doWork();
}
然后是并发执行器
public class ConcurrentRunner {
private static int threadCount = 0;
private Worker worker;
public void setWorker(Worker w){
worker = w;
}
private ExecutorService service = Executors.newCachedThreadPool();
ConcurrentRunner(int count ){
threadCount = count;
}
private final CountDownLatch countDownLatch = new CountDownLatch(threadCount);
public void run(){
for (int i = 0; i < threadCount; i++) {
Runnable runnable = new Runnable() {
public void run() {
try {
countDownLatch.await();
worker.doWork();
} catch (Exception e) {
e.printStackTrace();
}
}
};
service.execute(runnable);
//达到threadcount线程数量的时候,所有线程以前执行
countDownLatch.countDown();
}
}
}
下面进入正题,这个题目主要考察的是并发控制,当然你可以用整个方法都加锁来实现,但是效率低下,借鉴CAS的思想来实现是最优解决方案:
import java.util.HashMap;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
/**
* Created by yzy on 2018/10/31.
*/
public class Main {
/**
* 投票人数量
*/
public static final int VOTER_COUNT = 100;
/**
* 候选人数量
*/
public static final int CANDINATE_COUNT = 3;
/**
* 候选人
* @param args
*/
public static final String[] candinator = {"tom","lily","jimmy"} ;
// private static HashMap<String , Integer> result = new HashMap(3);
private static ConcurrentHashMap<String , Integer> result = new ConcurrentHashMap(3);
public static void main(String[] args) {
ConcurrentRunner concurrentRunner = new ConcurrentRunner(VOTER_COUNT);
concurrentRunner.setWorker(new Worker() {
@Override
public void doWork() {
Random random = new Random();
int index = random.nextInt(3);
System.out.println("who="+index);
String who = candinator[index];
// int num = result.get(who);
// result.put(who,1);
result.putIfAbsent(who,0);
int num = 0;
// while(!result.replace(who,num=result.get(who),num++)){
// while(!result.replace(who,num=result.get(who),++num)){
while(!result.replace(who,num=result.get(who),num + 1)){
}
}
});
concurrentRunner.run();
System.out.println("tom 票数" + result.get("tom"));
System.out.println("lily 票数 " + result.get("lily"));
System.out.println("jimmy 票数" + result.get("jimmy"));
}
}