3

我正在尝试使用 java 在并行端口上创建方波。到目前为止,我有这个实现。

public class Wave extends Thread {

    public Wave() {
        super();
        setPriority(MAX_PRIORITY);
    }

    @Override
    public void run() {
        Wave.high();
        LockSupport.parkNanos(20000000);
        Wave.low();
        LockSupport.parkNanos(20000000);
    }

    public static native void high();
    public static native void low();
}

其中 high() 和 low() 是使用 JNI 实现的(一个共享的 C 库控制并行端口)。它工作得很好;它会产生一个周期约为 40ms 的方波。当计算机空闲时,使用示波器看起来标准偏差约为 10 微秒。当计算机不空闲时,标准偏差变得更大。我认为这是因为发生了更多的上下文切换,线程在等待状态中停留的时间太长,并且没有准确地达到指定的 20 毫秒。

有没有办法让我的实现更准确?我知道我可以为此使用硬件,但我想知道我是否也可以使用软件来做到这一点。

是否可以选择“听”时钟并执行计时到毫秒的操作?

4

3 回答 3

1

仅仅“听”时钟并不能解决上下文切换导致抖动的问题。

如果您可以为此奉献一个核心:

这样,您应该能够实现非常低的抖动。

当然,如果任务只是简单地产生方波,那么这是对计算资源的非常低效的使用。

于 2012-05-03T12:23:33.110 回答
1

我认为会有两个抖动来源。

首先,Java 中的垃圾收集(可能还有其他后台进程,如 JIT)。对于您提供的代码,不应该有任何 gc。但如果这是更大系统的一部分,那么您可能会发现需要进行垃圾收集,并且它可能会改变运行时的时间。您可以尝试通过使用 jvm 设置 (java -X) 来改善这一点。

第二,系统调度器。除了 aix 的建议之外,您还可以提高进程的优先级并进行一些特定于 linux 的调整。 这篇文章解释了 linux 的一些问题。 ubuntu 有一个低延迟内核,你可以安装它,但我找不到它实际包含的信息,所以你可以在其他系统上做同样的事情(更新:我认为它可能包含这个补丁)。如果您想查找更多信息,“低延迟”是要搜索的关键思想,而在 linux 上进行音频处理的人往往是最关心这一点的人)。

于 2012-05-03T13:08:58.690 回答
0

如果您的上下文切换不会导致太多延迟,您可以尝试将线程停在给定时间,而不是给定时间间隔:

public class Wave extends Thread {
    private final Object BLOCKER = new Object();

    public Wave() {
        super();
        setPriority(MAX_PRIORITY);
    }

    @Override
    public void run() {
      // I suspect this should be running in an endless loop?
      for (;;) {
        Wave.high();
        long t1 = System.currentTimeMillis();

        // Round interval up to the next 20ms "deadline"
        LockSupport.parkUntil(BLOCKER, t1 + 20 - (t1 % 20));
        Wave.low();

        // Round interval up to the next 20ms "deadline"
        long t2 = System.currentTimeMillis();
        LockSupport.parkUntil(BLOCKER, t2 + 20 - (t2 % 20));
      }
    }

    public static native void high();
    public static native void low();
}

由于这依赖于 中的挂钟时间ms,而不是更精确的纳秒时间,因此这不适用于更高的频率。但这也可能不起作用,因为 GC(和其他进程)可能会在“不幸”的时间内中断该线程,从而导致相同的抖动。

当我在我的带有 JDK 6 的 Windows 7 四核上测试这个时,我每秒都有一些不可忽略的抖动,所以aix 的解决方案可能更好

于 2012-05-03T12:32:47.957 回答