不是吧阿 sir!System,java 面试问项目中遇到的技术难点
====================================
System 代表 System.currentTimeMillis
缓存时钟代表 使用静态成员变量做 System.currentTimeMillis 缓存的时钟类
200 线程-Tomcat 的默认线程数
可以看到 System.currentTimeMilli
s 并发性能并不算差,在次数较少(短期并发调用)的情况下甚至比单线程要强很多,而在单线程调用时效率也要比缓存时钟要高一倍左右。实际环境中几乎是达不到上述测试中的多线程长时间并发调用 System.currentTimeMillis 这样的情况的,因而我认为没有必要对 System.currentTimeMillis 做所谓的“优化”
这里没有做“new 一个对象”的测试,是因为并不是代码里写了 new Object(),JVM 就会真的会给你在堆内存里 new 一个对象。这是 JVM 的一个编译优化——逃逸分析:先分析要创建的对象的作用域,如果这个对象只在一个 method 里有效(局部变量对象),则属于未 方法逃逸,不去实际创建对象,而是你在 method 里调了对象的哪个方法,就把这个方法的代码块内联进来。只在线程内有效则属于未 线程逃逸,会创建对象,但会自动消除我们做的无用的同步措施。
最后
==
纸上得来终觉浅,绝知此事要躬行
最后奉上我的测试代码
public class CurrentTimeMillisTest {
public static void main(String[] args) {
int num = 10000000;
System.out.print("单线程"+num+"次 System.currentTimeMillis 调用总耗时: ");
System.out.println(singleThreadTest(() -> {
long l = System.currentTimeMillis();
},num));
System.out.print("单线程"+num+"次 CacheClock.currentTimeMillis 调用总耗时:");
System.out.println(singleThreadTest(() -> {
long l = CacheClock.currentTimeMillis();
},num));
System.out.print("并发"+num+"次 System.currentTimeMillis 调用总耗时: ");
System.out.println(concurrentTest(() -> {
long l = System.currentTimeMillis();
},num));
System.out.print("并发"+num+"次 CacheClock.currentTimeMillis 调用总耗时: ");
System.out.println(concurrentTest(() -> {
long l = CacheClock.currentTimeMillis();
},num));
}
/**
* 单线程测试
* @return
*/
private static long singleThreadTest(Runnable runnable,int num) {
long sum = 0;
for (int i = 0; i < num; i++) {
long begin = System.nanoTime();
runnable.run();
long end = System.nanoTime();
sum += end - begin;
}
return sum;
}
/**
* 并发测试
* @return
*/
private static long concurrentTest(Runnable runnable,int num) {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(200,200,60, TimeUnit.SECONDS,new LinkedBlockingQueue<>(num));
long[] sum = new long[]{0};
//闭锁基于 CAS 实现,并不适合当前的计算密集型场景,可能导致等待时间较长
CountDownLatch countDownLatch = new CountDownLatch(num);
for (int i = 0; i < num; i++) {
threadPoolExecutor.submit(() -> {
long begin = System.nanoTime();
runnable.run();
long end = System.nanoTime();
//计算复杂型场景更适合使用悲观锁
synchronized(CurrentTimeMillisTest.class) {
sum[0] += end - begin;
}
countDownLatch.countDown();
});
}
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
return sum[0];
}
/**
* 缓存时钟,缓存 System.currentTimeMillis()的值,每隔 20ms 更新一次
*/
public static class CacheClock{
评论