【发布时间】:2016-04-16 19:18:58
【问题描述】:
编辑:我用nanoTime() 做了一些println()ing,发现stepPins[pin].toggle() 需要4226 微秒。现在我需要找到一种更快的切换引脚的方法。
我正在编写一个程序来控制音乐软盘驱动器阵列。目前,我有一个方法每 10 微秒运行一次,并通过读取 01001011 形式的短片来标记必要的软盘,其中 1=tick floppy(有 8 张软盘)。
由于某种原因,代码运行速度太慢,导致音符频率偏离。
这里是方法和它的类:
public class Timer implements Runnable
{
@Override
public void run()
{
int i = Main.currentSteps.get(Main.time);
try
{
if (Main.time > Main.maxTime)
{
Main.executor.remove(Main.timer);
FloppyController.resetAll();
}
if ((i & 1) == 1)
{
FloppyController.stepPin(0);
}
if ((i & 2) == 2)
{
FloppyController.stepPin(1);
}
if ((i & 4) == 4)
{
FloppyController.stepPin(2);
}
if ((i & 8) == 8)
{
FloppyController.stepPin(3);
}
if ((i & 16) == 16)
{
FloppyController.stepPin(4);
}
if ((i & 32) == 32)
{
FloppyController.stepPin(5);
}
if ((i & 64) == 64)
{
FloppyController.stepPin(6);
}
if ((i & 128) == 128)
{
FloppyController.stepPin(7);
}
}
catch (Exception e) {}
Main.time++;
}
}
以及它的价值,我的Main.java 课程的相关部分:
public class Main
{
public static ArrayList<Short> currentSteps;
public static ArrayList<Note> all = new ArrayList<Note>();
public static long maxTime = 0;
public static ScheduledThreadPoolExecutor executor;
public static Timer timer;
public static int time;
public static void main(String[] args) throws InterruptedException, InvalidMidiDataException, IOException, MidiUnavailableException
{
//initialize
FloppyController.init();
currentSteps = new ArrayList<Short>();
FloppyController.resetAll();
for (int o = 0; o < Math.ceil(maxTime / 10); o++)
{
currentSteps.add((short) 0);
}
//populate list
for (Note n : all)
{
for (int a = Math.round(n.timeStart / 10); a <= Math.round(n.timeEnd / 10); a += n.wait)
{
currentSteps.set(a, (short) (currentSteps.get(a) + (((currentSteps.get(a) & (short) Math.pow(2, n.channel)) == Math.pow(2, n.channel)) ? 0 : Math.pow(2, n.channel))));
}
}
//start play executions
executor = new ScheduledThreadPoolExecutor(1);
long resolution = 10; //# of microsecond iterations
timer = new Timer();
executor.scheduleAtFixedRate(timer, 0, resolution, TimeUnit.MICROSECONDS);
}
如何优化Timer.class的run()方法?
我也在考虑将 currentSteps ArrayList 更改为 HashMap,并且只包含非零值及其相应时间作为键,因为我在运行它的 Raspberry Pi 上遇到内存问题。
这里是stepPin 方法:
public static void stepPin(int pin) throws InterruptedException
{
if (pinPositions[pin] >= 79)
{
changeDirection(pin, true);
}
else if(pinPositions[pin] < 0)
{
changeDirection(pin, false);
}
stepPins[pin].toggle();
stepPins[pin].toggle();
pinPositions[pin] += pinDirections[pin].isLow() ? 1 : -1;
}
【问题讨论】:
-
stepPin是否会阻塞(直到软盘发出声音)? -
将方法添加到主要问题,可能是一个好主意来安排而不是运行
stepPin() -
定时器不准确,它会尽力每x ms运行一次,但这取决于底层系统。
-
@TT。有更好的选择吗?至少它比 Thread.sleep 好:P
-
请注意 println() 也有开销,Java 中的控制台 IO 传统上很慢。我建议改为写入缓冲文件。
标签: java optimization timer raspberry-pi