java - Thread.sleep() 的精确替代方案

标签 java thread-sleep scheduledexecutorservice

我需要一种方法将线程延迟精确的毫秒数(乐谱播放应用程序)。我知道Thread.sleep()的精度不是很好,所以我决定改为使用ScheduledExecutorService。我这样做的方法如下:

... //some code
int duration = 100; //delay for 100ms
CountDownLatch l = new CountDownLatch(1);
Executors.newScheduledThreadPool(1).schedule(l::countDown, duration, TimeUnit.MILLISECONDS);
l.await();
... //continue execution

这是一个好方法吗?我主要担心 CountDownLatch 以及它可能增加的任何延迟(如果有)。

谢谢。

最佳答案

因此,由于一些问题,您的解决方案并不好。您将失去通过使用 await 使用调度执行程序服务所获得的优势。await 将使当前线程进入休眠状态,然后操作系统需要在启动之前再次调度它。

我使用三种不同的技术制作了一个示例。旋转等待,使用 thread.sleep 并使用您的预定执行器想法。自旋等待是最准确的,为 7002 毫秒,而其他两个解决方案完成后超过 8300 毫秒。

import java.util.concurrent.*;

public class DwellTimes{

    static public void spinWait(long ms){
        long end = System.nanoTime() + ms*1000000;
        long current = System.nanoTime();
        while( current < end){
            current = System.nanoTime();
        }
    }
    
    static public void sleepWait(long ms){
        try{
            Thread.sleep(ms);
        } catch(Exception e){
            throw new RuntimeException(e);
        }
    }
    
    static ScheduledExecutorService ses = Executors.newScheduledThreadPool(1);
     
    static public void scheduleWait(long ms){
        try{
            CountDownLatch l = new CountDownLatch(1);
            ses.schedule(l::countDown, ms, TimeUnit.MILLISECONDS);
            l.await();
        } catch(Exception e){
            throw new RuntimeException(e);
        }
    }
    
   
    
    public static void main(String[] args){
        long start = System.currentTimeMillis();
        for(int i = 0; i<1000; i++){
            scheduleWait(7);
        }
        long end = System.currentTimeMillis() - start;
        System.out.println( end + "ms elapsed");
    }
}

对于 sleep /等待风格的流程,旋转等待将是最准确的,因为它不会释放线程。它只会继续火爆。

您的计划执行程序示例的问题在于您实际上并未使用计划。您想要安排您的任务。

public static void scheduleWork(){
    CountDownLatch latch = new CountDownLatch(1000);
    ses.scheduleAtFixedRate(latch::countDown, 7, 7, TimeUnit.MILLISECONDS);
    try{
        latch.await();
    } catch(Exception e){
        throw new RuntimeException(e);
    }
}

最后一个示例可能是管理一致计时的最佳方法,因为您不会继续累积错误。例如,如果您的操作需要几毫秒,则下一个操作将不会延迟除非这几毫秒超过了时间段

关于java - Thread.sleep() 的精确替代方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66256632/

相关文章:

java - 如何将我经常使用的方法添加到android studio?

包含多个可以作为整数写入和读取的变量的Java结构?

java - 如何在 while 循环内中断并继续 try-catch?

java - 提前/快速启动 ScheduledThreadPoolExecutor 中的任务

java - 如何安排周期性任务,但在满足条件时停止并返回结果(Java)

java - 错误 : Could not find or load main class on running the java file

java - 类型转换 "with"接口(interface)

c# - 如何在不卡住 WPF 应用程序中的 UI 线程的情况下让子线程休眠?

java - 正在运行但调试期间无法停止线程

java - 使用循环迭代线程并处理多个结果