我正在尝试对我的服务进行一些性能测试。所以我为此编写了一个多线程程序。它将与几个线程平行地进行我的服务,然后测量每个线程返回的时间。
我正在进行更新并获取地图的方式将是线程安全的。对?因为我发现很难调试这个Mutltithreading程序,看看我的程序是否正常工作。任何人都可以帮我解决这个多线程程序
private static ConcurrentHashMap<Long, Long> histogram = new ConcurrentHashMap<Long, Long>();
public static void main(String[] args) {
ExecutorService service = Executors.newFixedThreadPool(10);
for (int i = 0; i < 1 * 1000; i++) {
service.submit(new ThreadTask(i, histogram));
}
service.shutdown();
while (!service.isTerminated()) {
}
ThreadTask.report();
}
class ThreadTask implements Runnable {
private int id;
private RestTemplate restTemplate = new RestTemplate();
private String result;
private static ConcurrentHashMap<Long, Long> mapData;
public ThreadTask(int id, ConcurrentHashMap<Long, Long> histogram) {
this.id = id;
this.mapData = histogram;
}
@Override
public void run() {
long start_time = System.currentTimeMillis();
result = restTemplate.getForObject("", String.class);
long difference = (System.currentTimeMillis() - start_time);
Long count = getMethod(mapData, difference);
if (count != null) {
count++;
putMethod(mapData, difference, count);
} else {
putMethod(mapData, difference, Long.valueOf(1L));
}
}
private synchronized void putMethod(ConcurrentHashMap<Long, Long> hg2, long difference, Long count) {
hg2.put(Long.valueOf(difference), count);
}
private synchronized Long getMethod(ConcurrentHashMap<Long, Long> hg2, long difference) {
return hg2.get(difference);
}
public static void report() {
System.out.println(mapData);
}
}
根据以下建议更新了代码基础 -
private static RestTemplate restTemplate = new RestTemplate();
private static String result = null;
private static ConcurrentHashMap<Long, AtomicLong> histogram = new ConcurrentHashMap<Long, AtomicLong>();
public static void main(String[] args) {
ExecutorService service = Executors.newFixedThreadPool(10);
for (int i = 0; i < 1 * 1000; i++) {
service.submit(new ThreadTask(i, histogram));
}
service.shutdown();
while (!service.isTerminated()) {
}
ThreadTask.report();
}
class ThreadTask implements Runnable {
private int id;
private static RestTemplate restTemplate = new RestTemplate();
private String result;
private static ConcurrentHashMap<Long, AtomicLong> hg;
public ThreadTask(int id, ConcurrentHashMap<Long, AtomicLong> histogram) {
this.id = id;
this.hg = histogram;
}
@Override
public void run() {
long start_time = System.currentTimeMillis();
result = restTemplate.getForObject("", String.class);
long difference = (System.currentTimeMillis() - start_time);
final AtomicLong before = hg.putIfAbsent(difference, new AtomicLong(1L));
if (before != null) {
before.incrementAndGet();
}
}
public static void report() {
System.out.println(mapData);
}
}
任何人都可以看一下,让我知道这次我是否做对了?
答案 0 :(得分:2)
不,您的代码肯定是不是线程安全的,因为整个更新操作不是原子的。您读取一个值,递增它并回写。到那时,另一个线程可能已经增加了相同的直方图条目,现在你正在保存一个陈旧的值,有效地“吞下”一个命中。
我的建议:在整个更新操作中使用synchronized (histogram) { ... }
。但是,您不需要单独的同步方法。
如果您需要无锁解决方案,请使用ConcurrentHashMap<Long, AtomicLong>
并使用此代码进行更新:
final Long before = histogram.putIfAbsent(difference, new AtomicLong(1L));
if (before != null) before.incrementAndGet();
答案 1 :(得分:1)
您不需要使用ConcurrentHashMap同步
您应该多次运行代码来预热代码。我会忽略前10,000次,然后运行测试至少2到10秒。
答案 2 :(得分:1)
查看番石榴的AtomicLongMap。