写点什么

不是吧阿 sir!System,java 面试问项目中遇到的技术难点

用户头像
极客good
关注
发布于: 刚刚

====================================



System 代表 System.currentTimeMillis



缓存时钟代表 使用静态成员变量做 System.currentTimeMillis 缓存的时钟类



200 线程-Tomcat 的默认线程数


可以看到 System.currentTimeMilli


【一线大厂Java面试题解析+核心总结学习笔记+最新架构讲解视频+实战项目源码讲义】
浏览器打开:qq.cn.hn/FTf 免费领取
复制代码


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{

用户头像

极客good

关注

还未添加个人签名 2021.03.18 加入

还未添加个人简介

评论

发布
暂无评论
不是吧阿sir!System,java面试问项目中遇到的技术难点