让我们暂停一微秒

低延迟Java应用程序中的许多基准测试涉及必须在一定负载下测量系统。 这就要求保持事件进入系统的稳定吞吐量,而不是在没有任何控制的情况下以全油门将事件泵入系统。

我经常要做的任务之一是在事件之间暂停生产者线程一小段时间。 通常,此时间量为个位数微秒。

那么如何在此时间内暂停线程? 大多数Java开发人员会立即想到Thread.sleep() 。 但这是行不通的,因为Thread.sleep()仅下降到毫秒,并且比我们暂停所需的时间(以微秒为单位)长一个数量级。

我在StackOverflow上看到一个答案,将用户指向TimeUnit.MICROSECONDS.sleep()以便睡眠少于一毫秒。 引用JavaDoc ,这显然是不正确的:

使用此时间单位执行Thread.sleep 。 这是一种方便的方法,可以将时间参数转换为Thread.sleep方法所需的形式。

因此,您将无法获得比Thread.sleep(1)相似的1毫秒的暂停。 (您可以尝试下面的代码示例来证明这一点)。

这样做的原因是这种暂停方法(即使线程进入睡眠状态并唤醒它)永远不会足够快或准确到不足一毫秒。

在这一点上我们应该介绍的另一个问题是Thread.sleep(1)到底有多精确? 我们将在稍后再讨论。

当我们想暂停一微秒时,另一个选择是使用LockSupport.parkNanos(x) 。 使用以下代码停泊1微秒实际上需要约10us。 它比TimeUnit.sleep()/ Thread.sleep()更好,但并不真正适合目的。 100us之后,它的确进入了同一个球场,并且变化仅为50%。

package nanotime;import java.util.Arrays;
import java.util.concurrent.TimeUnit;/*** Created by daniel on 28/10/2015.*/
public class NanoTimer {public static void main(String[] args) throws InterruptedException {long[] samples = new long[100_000];int pauseInMillis = 1;for (int i = 0; i < samples.length; i++) {long firstTime = System.nanoTime();LockSupport.parkNanos(pauseInMicros);long timeForNano = System.nanoTime() - firstTime;samples[i] = timeForNano;}System.out.printf("Time for LockSupport.parkNanos() %.0f\n", Arrays.stream(samples).average().getAsDouble());}
}

解决我们问题的方法是使用System.nanoTime() 。 通过忙于等待对System.nanoTime的调用,我们将能够暂停一微秒。 我们将在一秒钟内看到此代码,但首先让我们了解System.nanosecond()的准确性。 至关重要的是,执行对System.nanoSecond()的调用需要多长时间。

这是一些可以完全做到这一点的代码:

package nanotime;public class NanoTimer {public static void main(String[] args) throws InterruptedException {long[] samples = new long[1_000_000];for (int i = 0; i < samples.length; i++) {long firstTime = System.nanoTime();long timeForNano = System.nanoTime() - firstTime;samples[i] = timeForNano;}System.out.printf("Time for call to nano %.0f nanseconds", Arrays.stream(samples).average().getAsDouble());}
}

在我的MBP上,从一台机器到另一台机器,数字将有所不同,大约为40纳秒。

这告诉我们,我们应该能够测量到大约40纳秒的精度。 因此,应该很容易测量1微秒(1000纳秒)。

这是忙碌的等待方法,“暂停”了微秒:

package nanotime;import java.util.Arrays;
/*** Created by daniel on 28/10/2015.*/
public class NanoTimer {public static void main(String[] args) throws InterruptedException {long[] samples = new long[100_000];int pauseInMicros = 1;for (int i = 0; i < samples.length; i++) {long firstTime = System.nanoTime();busyWaitMicros(pauseInMicros);long timeForNano = System.nanoTime() - firstTime;samples[i] = timeForNano;}System.out.printf("Time for micro busyWait %.0f\n", Arrays.stream(samples).average().getAsDouble());}public static void busyWaitMicros(long micros){long waitUntil = System.nanoTime() + (micros * 1_000);while(waitUntil > System.nanoTime()){;}}
}

该代码等待一微秒,然后乘以等待时间。 在我的机器上,我得到1,115纳秒,准确度在90%左右。

当您等待更长的时间时,精度会提高,10毫秒需要10,267纳秒,即约97%的准确度,而100毫秒需要100,497纳秒,即约99.5%的准确度。

那么Thread.sleep(1) ,这有多精确?

这是该代码:

package nanotime;import java.util.Arrays;
import java.util.concurrent.TimeUnit;/*** Created by daniel on 28/10/2015.*/
public class NanoTimer {public static void main(String[] args) throws InterruptedException {long[] samples = new long[100_000];int pauseInMillis = 1;for (int i = 0; i < samples.length; i++) {long firstTime = System.nanoTime();Thread.sleep(pauseInMicros);long timeForNano = System.nanoTime() - firstTime;samples[i] = timeForNano;}System.out.printf("Time for micro sleep %.0f\n", Arrays.stream(samples).average().getAsDouble());}
}

1毫秒睡眠的平均时间(以纳秒为单位)为1,295,509。 准确率只有〜75%。 对于几乎所有内容,它可能已经足够好了,但是如果您想要精确的毫秒级暂停,那么忙碌的等待会更好。 当然,您需要记住繁忙的等待,按照定义,繁忙的等待会使您的线程繁忙,并会花费您CPU的时间。

汇总表

暂停方式 1us 10us 100us 1000us / 1ms 10,000us / 10ms
TimeUnit.Sleep() 1284.6 1293.8 1295.7 1292.7 11865.3
LockSupport.parkNanos() 8.1 28.4 141.8 1294.3 11834.2
忙等待 1.1 10.1 100.2 1000.2 10000.2

结论

  • 如果您想暂停不到一毫秒,则需要忙于等待
  • System.nanoSecond()大约需要40ns
  • Thread.sleep(1)的准确率只有75%
  • 忙于等待超过10us以上的时间几乎是100%准确的
  • 繁忙的等待将占用CPU

翻译自: https://www.javacodegeeks.com/2015/11/lets-pause-for-a-microsecond.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/357121.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

浏览器各个属性的作用

作为前端程序员不可避免的会和浏览器打交道&#xff0c;所以要对浏览器的各个属性的作用进行了解&#xff0c;方便开发及调试&#xff0c;这里以谷歌浏览器为例进行简单的介绍。一是巩固对浏览器属性的认识&#xff0c;二是方便大家的学习。首先打开谷歌浏览器按F12查看控制台属…

Moment.js日期处理库的使用

Moment.jsMoment.js是一个轻量级的JavaScript时间库&#xff0c;它方便了日常开发中对时间的操作&#xff0c;提高了开发效率。这个在一些金融保险公司会经常用到&#xff0c;比如一下时间的格式化处理&#xff0c;时间的选择等等。这个比较好的地方是可以格式化时间&#xff0…

spring ldap_Spring 3,Spring Web Services 2和LDAP安全

spring ldap今年的开局很好&#xff0c;其中另一个“截止日期不会改变” /“跳过所有繁文tape节” / “狂野西部”类型的项目中&#xff0c;我必须弄清楚并使用相对而言实现一些功能。新的库和技术需要进行更改&#xff0c;Spring 3并不是新增功能&#xff0c;但是在Java 5&…

转: 微博的多机房部署的实践(from infoq)

转: http://www.infoq.com/cn/articles/weibo-multi-idc-architecture 在国内网络环境下&#xff0c;单机房的可靠性无法满足大型互联网服务的要求&#xff0c;如机房掉电&#xff0c;光缆被挖的情况也发生过。微信就曾发生大面积故障&#xff0c;包括微信信息无法发出、无法刷…

知道这些性能优化手段,工资起码提升一倍

1.什么是性能?性能指标有哪些&#xff1f;计算机的性能&#xff0c;其实和我们干体力劳动很像&#xff0c;好比是我们要搬东西。对于计算机的性能&#xff0c;我们需要有个标准来衡量。这个标准中主要有两个指标。第一个是响应时间&#xff08;Response time&#xff09;或者叫…

JAX-RS和JSON-P集成

这篇简短的文章讨论了JAX-RS 2.0中对JSON-P的支持 JSON-P…&#xff1f; JSON处理API &#xff08;JSON-P&#xff09;是Java EE 7中引入的。 它提供了用于处理JSON数据的标准API&#xff0c;并且与XML对应的JAXP非常相似。 JSON-B &#xff08;JSON绑定&#xff09;API已在Ja…

亲手把360奇安信软件卸载了,爽!

由于工作原因&#xff0c;在上一家公司安装了360奇安信安全软件&#xff0c;到了下一个公司还需要安装另一个安全软件&#xff0c;这个必须要卸载&#xff0c;卸载&#xff01;卸载&#xff01;但是卸载需要输入密码&#xff0c;没有密码还输入卸载不了&#xff0c;我曾经联系3…

VM虚拟机中CentOS6.4操作系统安装一

在 VMware中鼠标单击“编辑虚拟机设置”&#xff0c;在弹出的“虚拟机设置”对话框中的“硬件”标签中选择“CD/DVD&#xff08;IDE&#xff09;”&#xff0c;然后在右侧的“CD /DVD&#xff08;IDE&#xff09;”连接选项中选择“使用ISO映像文件”&#xff0c;使用“浏览”按…

vue基础教程总结篇,用最短的时间入门vue.js(持续更新...)

目前&#xff0c;vue已经成为前端工程师必会的框架之一&#xff0c;这里简单总结一下&#xff0c;可以让您快速的入门vue,师傅带进门&#xff0c;修行靠个人&#xff0c;最主要的还是自己多动手&#xff0c;多实践&#xff0c;本专栏会持续更新。 1.vue安装教程及简介 2.vue计…

gcc代码反汇编查看内存分布[2]: arm-linux-gcc

arm-none-linux-gnueabi-gcc -v gcc version 4.4.1 (Sourcery G Lite 2010q1-202) 重点: 代码中的内存分配, 地址从低到高: 代码段(RO, 保存函数代码) --> 只读数据段(RO, 保存常量) --> 数据段(RW, 已初始化并且初始值不为0的全局变量和静态变量) -->bss段(RW, 未初…

关于SP一些响应码的API返回码及解析集合

在一些金融的行业&#xff08;银行、证券、保险等&#xff09;&#xff0c;如果接触了一些中间件&#xff0c;比如长城、恒银、广电等一些厂商的设备&#xff0c;不同的厂商有不同的一些规范&#xff0c;在应用开发的过程中难免会和中间件的错误码打交道&#xff0c;这里总结一…

eclipselink_Java EE 7的高峰– EclipseLink的多租户示例

eclipselink水族馆是有关所有相关规范和参考实现中有关Java EE进度的灵感和最新信息的重要来源。 他们从Oracle的Shaun Smith&#xff08; 博客 / 推特 &#xff09;获取了有关EclipseLink作为开源项目的地位和未来的演讲。 他介绍了将在EclipseLink 2.4中提供的所有新功能&…

我们的团队目标

我们的团队目标(WBS)&#xff1a; 完成一个规范的电脑应用程序&#xff0c;实现各个模块功能&#xff0c;让用户能够随时的存放自己的代码并且方便的提取到自己想要的代码进行查阅和修改。 团队项目的主要工作项目&#xff1a; 利用sql数据库和eclipse实现文件的存取查询。 个人…

关于一些常见智柜问题的分析及解决办法

竟然还有小伙伴感觉自研项目不好的小伙伴&#xff1f;渐渐感觉不管是在小公司或者在大公司&#xff0c;能有一个值得奋斗的远方就可以了&#xff0c;比如薪资高&#xff0c;钱多事少离家近&#xff0c;自己真的对自己目前做的事情感兴趣&#xff0c;否则干啥都感觉没劲&#xf…

流绩效–您的想法

上周&#xff0c;我介绍了一些有关Java 8流性能的基准测试结果。 你们和gal足够感兴趣&#xff0c;可以留下一些想法&#xff0c;还有哪些可以介绍。 这就是我所做的&#xff0c;这是结果。 总览 最后一篇文章的序言也适用于此。 阅读它&#xff0c;以找出所有数字为何撒谎&a…

java中JVM的原理

一、java虚拟机的生命周期&#xff1a; Java虚拟机的生命周期 一个运行中的Java虚拟机有着一个清晰的任务&#xff1a;执行Java程序。程序开始执行时他才运行&#xff0c;程序结束时他就停止。你在同一台机器上运行三个程序&#xff0c;就会有 三个运行中的Java虚拟机。 Java虚…

2022将至,前端程序员们应该一起放个烟花庆祝一下,走起

前言&#xff1a;小时候&#xff0c;在我印象中&#xff0c;每到快过年的时候就有很多卖炮仗的&#xff0c;一般也就是阳历的12月份到明年的正月15号卖炮仗的商家比较多&#xff0c;省下买辣条的钱去买炮仗&#xff0c;在老家也就过年和除夕两天及正月15日这几天放烟花和炮仗比…

微信红包封面开放平台序列号

微信红包封面开放平台是一款可以领取微信红包封面的平台&#xff0c;最近网上非常流行好玩的微信红包封面&#xff0c;每一种封面都极具特色&#xff0c;让你的微信红包与众不同&#xff0c;还可以定制专属的微信红包封面&#xff0c;不过名额有限&#xff0c;这边为大家带来这…

ios多线程 -- NSOperation 简介

NSOperation的作⽤&#xff1a;配合使用NSOperation和NSOperationQueue也能实现多线程编程 NSOperation和NSOperationQueue实现多线程的具体步骤&#xff1a; 1&#xff09;先将需要执行的操作封装到一个NSOperation对象中 2&#xff09;然后将NSOperation对象添加到NSOpera…

在没有复杂插件的情况下从Eclipse启动和调试Tomcat

像Eclipse这样的现代IDE提供了各种插件来简化Web开发。 但是&#xff0c;我相信将Tomcat作为“常规” Java应用程序启动仍然可以提供最佳的调试体验。 大多数时候&#xff0c;这是因为这些工具将Tomcat或任何其他servlet容器作为外部进程启动&#xff0c;然后在其上附加一个远程…