Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/svg/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java try资源块中可自动关闭的延迟执行_Java_Performance - Fatal编程技术网

Java try资源块中可自动关闭的延迟执行

Java try资源块中可自动关闭的延迟执行,java,performance,Java,Performance,我注意到在自动关闭对象上执行close方法有时会延迟。它通常在一两毫秒内执行,但有时需要100毫秒或更长时间 我找不到描述使用资源进行尝试的预期时间的Java文档。有人能解释一下为什么有时会有如此大的延迟吗 下面是一个测试来证明这一点。结果各不相同,但如果运行的时间足够长,结果开始显示close方法的延迟执行 public class ClosableTest { public class TimerResource implements AutoCloseable {

我注意到在自动关闭对象上执行close方法有时会延迟。它通常在一两毫秒内执行,但有时需要100毫秒或更长时间

我找不到描述使用资源进行尝试的预期时间的Java文档。有人能解释一下为什么有时会有如此大的延迟吗

下面是一个测试来证明这一点。结果各不相同,但如果运行的时间足够长,结果开始显示close方法的延迟执行

public class ClosableTest {
    public class TimerResource implements AutoCloseable {
        private Instant startTime;
        private long sleepTime;
        private long actualTime;

        public TimerResource() {
            startTime = Instant.now();
        }

        public void setSleepTime(long sleepTime) {
            this.sleepTime = sleepTime;
        }

        public void setActualTime(long actualTime) {
            this.actualTime = actualTime;
        }

        @Override
        public void close() throws Exception {
            long closeTime = Duration.between(startTime, Instant.now()).toMillis();
            //System.out.println(String.format("%s: Sleep time: %d; Actual time: %d; Closed time: %s", Thread.currentThread().getName(), sleepTime, actualTime, closeTime));
            if (closeTime > actualTime+5) {
                System.out.println("Close took more than 5ms");
                System.out.println(String.format("\t%s: Sleep time: %d; Actual time: %d; Closed time: %s", Thread.currentThread().getName(), sleepTime, actualTime, closeTime));
            }
        }
    }

    @Test
    public void timingTest() {
        Instant start;
        long realDuration;

        for (int i = 0; i < 100; i++) {
            try (TimerResource timer = new TimerResource()) {
                start = Instant.now();

                long sleepTime = 10L + (long) (400 * Math.random());
                timer.setSleepTime(sleepTime);
                Thread.sleep(sleepTime);

                realDuration = Duration.between(start, Instant.now()).toMillis();
                timer.setActualTime(realDuration);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
公共类ClosableTest{
公共类TimerResource实现自动关闭{
私人即时启动时间;
私人长时间睡眠;
私人长实际时间;
公共时间资源(){
startTime=Instant.now();
}
公共空闲设置睡眠时间(长睡眠时间){
this.sleepTime=睡眠时间;
}
公共无效设置实际时间(长实际时间){
this.actualTime=实际时间;
}
@凌驾
public void close()引发异常{
long closeTime=Duration.between(startTime,Instant.now()).toMillis();
//System.out.println(String.format(“%s:睡眠时间:%d;实际时间:%d;关闭时间:%s”,Thread.currentThread().getName(),sleepTime,actualTime,closeTime));
如果(关闭时间>实际时间+5){
System.out.println(“关闭时间超过5毫秒”);
System.out.println(String.format(“\t%s:睡眠时间:%d;实际时间:%d;关闭时间:%s”,Thread.currentThread().getName(),sleepTime,actualTime,closeTime));
}
}
}
@试验
公共无效时间测试(){
即时启动;
持续时间长;
对于(int i=0;i<100;i++){
try(TimerResource timer=new TimerResource()){
start=Instant.now();
长睡眠时间=10L+(长)(400*Math.random());
定时器。设置睡眠时间(睡眠时间);
睡眠(睡眠时间);
realDuration=Duration.between(start,Instant.now()).toMillis();
timer.setActualTime(realDuration);
}捕获(例外e){
e、 printStackTrace();
}
}
}
}

我认为这两种情况之间不应该有显著的差异。根据java<代码>尝试使用资源如下翻译

假设您对资源的尝试如下所示

try ({VariableModifier} R Identifier = Expression ...)
    Block
将转化为:

{
    final {VariableModifierNoFinal} R Identifier = Expression;
    Throwable #primaryExc = null;

    try ResourceSpecification_tail
        Block
    catch (Throwable #t) {
        #primaryExc = #t;
        throw #t;
    } finally {
        if (Identifier != null) {
            if (#primaryExc != null) {
                try {
                    Identifier.close();
                } catch (Throwable #suppressedExc) {
                    #primaryExc.addSuppressed(#suppressedExc);
                }
            } else {
                Identifier.close();
            }
        }
    }
}
所以很明显,try with resource和normal
try catch
几乎相同。唯一的区别是,您可能会放置/或不放置在翻译
时生成的所有检查,请尝试使用资源

有人能解释一下为什么有时会有这么大的 耽搁


有时,较大的延迟可能是由于几个原因造成的,如当时的CPU使用情况、可用内存、GC等。

我认为这两种情况之间不应该有显著的差异。根据java<代码>尝试使用资源
如下翻译

假设您对资源的尝试如下所示

try ({VariableModifier} R Identifier = Expression ...)
    Block
将转化为:

{
    final {VariableModifierNoFinal} R Identifier = Expression;
    Throwable #primaryExc = null;

    try ResourceSpecification_tail
        Block
    catch (Throwable #t) {
        #primaryExc = #t;
        throw #t;
    } finally {
        if (Identifier != null) {
            if (#primaryExc != null) {
                try {
                    Identifier.close();
                } catch (Throwable #suppressedExc) {
                    #primaryExc.addSuppressed(#suppressedExc);
                }
            } else {
                Identifier.close();
            }
        }
    }
}
所以很明显,try with resource和normal
try catch
几乎相同。唯一的区别是,您可能会放置/或不放置在翻译
时生成的所有检查,请尝试使用资源

有人能解释一下为什么有时会有这么大的 耽搁

有时,较大的延迟可能是由于几个原因造成的,如当时的CPU使用情况、可用内存、GC等。

立即调用close()。然而,当你试图以经验来确定这一点时,你只会像你的基准一样可靠

顺便说一句,如果您在一个紧密循环中调用
System.nanoTime()
,您可以看到由于进程被重新调度而导致的1-50毫秒的时间跳跃。通过运行此测试工具,您可以在计算机上看到这一点

如果你看一下这个例子的字节码

public static void main(String... args) {
    try (PrintWriter pw = new PrintWriter(System.out)) {
        pw.println("Hello World");
    }
}
您可以看到,在println之后立即调用close

   L11
    LINENUMBER 13 L11
    NEW java/io/PrintWriter
    DUP
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    INVOKESPECIAL java/io/PrintWriter.<init> (Ljava/io/OutputStream;)V
    ASTORE 1
   L12
    ACONST_NULL
    ASTORE 2
   L3
    LINENUMBER 14 L3
    ALOAD 1
    LDC "Hello World"
    INVOKEVIRTUAL java/io/PrintWriter.println (Ljava/lang/String;)V
   L4
    LINENUMBER 15 L4
    ALOAD 1
    IFNULL L13
    ALOAD 2
    IFNULL L14
   L0
    ALOAD 1
    INVOKEVIRTUAL java/io/PrintWriter.close ()V
   L1
    GOTO L13
   L2
L11
线路号13 L11
新的java/io/PrintWriter
重复
GETSTATIC java/lang/System.out:Ljava/io/PrintStream;
调用特定的java/io/PrintWriter。(Ljava/io/OutputStream;)V
阿斯托尔1号
L12
空的
阿斯托尔2号
L3
行号14 L3
阿洛德1号
最不发达国家“你好,世界”
invokeVirtualJava/io/PrintWriter.println(Ljava/lang/String;)V
L4
线路号15 L4
阿洛德1号
IFNULL L13
阿洛德2号
IFNULL L14
L0
阿洛德1号
invokeVirtualJava/io/PrintWriter.close()V
L1
转到L13
L2
为简洁起见,我删除了try/finally字节码,除非有可丢弃的,否则不会执行该字节码。

立即调用close()。然而,当你试图以经验来确定这一点时,你只会像你的基准一样可靠

顺便说一句,如果您在一个紧密循环中调用
System.nanoTime()
,您可以看到由于进程被重新调度而导致的1-50毫秒的时间跳跃。通过运行此测试工具,您可以在计算机上看到这一点

如果你看一下这个例子的字节码

public static void main(String... args) {
    try (PrintWriter pw = new PrintWriter(System.out)) {
        pw.println("Hello World");
    }
}
您可以看到,在println之后立即调用close

   L11
    LINENUMBER 13 L11
    NEW java/io/PrintWriter
    DUP
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    INVOKESPECIAL java/io/PrintWriter.<init> (Ljava/io/OutputStream;)V
    ASTORE 1
   L12
    ACONST_NULL
    ASTORE 2
   L3
    LINENUMBER 14 L3
    ALOAD 1
    LDC "Hello World"
    INVOKEVIRTUAL java/io/PrintWriter.println (Ljava/lang/String;)V
   L4
    LINENUMBER 15 L4
    ALOAD 1
    IFNULL L13
    ALOAD 2
    IFNULL L14
   L0
    ALOAD 1
    INVOKEVIRTUAL java/io/PrintWriter.close ()V
   L1
    GOTO L13
   L2
L11
线路号13 L11
新的java/io/PrintWriter
重复
GETSTATIC java/lang/System.out:Ljava/io/PrintStream;
调用特定的java/io/PrintWriter。(Ljava/io/OutputStream;)V
阿斯托尔1号
L12
空的
阿斯托尔2号
L3
行号14 L3
阿洛德1号
最不发达国家“你好,世界”
invokeVirtualJava/io/PrintWriter.println(Ljava/lang/String;)V
L4
线路号15 L4
阿洛德1号
IFNULL L13
阿洛德2号
IFNULL L14
L0
阿洛德1号
invokeVirtualJava/io/PrintWriter.close()V
L1
转到L13
L2
为简洁起见,我删除了try/finally字节码,除非有可丢弃的,否则不会执行该字节码。

这可能会有很多字节码