我正在尝试实现一个实时执行的应用程序,其中按钮点击事件会将任务分配给一个线程,这将调用 midi方法来播放一些音乐。单击按钮时,必须立即启动音乐。 midi代码在Runnable类的run方法中实现。但是,在按钮点击事件本身采用超过2毫秒之后,要达到第一个运行方法声明。 我尝试使用Executor Service,因为它可以收集新创建的线程,并减少线程引起的时间延迟。我是ExecutorService应用程序的新手。我观察到的是第一次点击按钮时它超过2毫秒,但重新启动时延迟减少。但在某些阶段,它也会增加到超过4毫秒。每次延迟如何保持在不到1毫秒。有没有办法使用ExecutorService或任何其他服务提供商...任何帮助将是欣赏。 这是我的代码,我如何使用ExecutorService,如果没有正确使用它,请帮我纠正。
private static TestExecutorSerivice obj=new TestExecutorSerivice(3);;
private void handlePlayButtonAction(ActionEvent event) throws InterruptedException {
Handler.click=System.nanoTime();
obj.run();
}
TestExecutorService.java
public class TestExecutorSerivice implements Runnable {
private ExecutorService pool;
public TestExecutorSerivice( int poolSize)
{
pool = Executors.newFixedThreadPool(poolSize);
}
public void run() {
try {
pool.execute(new Handler());
} catch (Exception ex) {
pool.shutdown();
}
}
}
class Handler implements Runnable {
public static long click;
public void run() {
System.out.println("time taken "+(((double)System.nanoTime()-click)/1000000));
}
}
输出:
time taken 2.107673
time taken 1.336642
time taken 0.185161
time taken 0.130059
time taken 1.007243
time taken 4.486807
time taken 0.092783
答案 0 :(得分:1)
延迟可能是由于操作系统调度造成的,在这种情况下,可能没什么可做的,或者因为线程池忙于启动线程,或者因为您的池已被完全使用。
您可以尝试使用更大的池并预启动所有线程。类似的东西:
ThreadPoolExecutor tpe = new ThreadPoolExecutor(poolSize, poolSize, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>());
tpe.prestartAllCoreThreads();
pool = tpe;
例如,池大小为10。
(第一行相当于Executors.newFixedThreadPool
)
如果你仍然观察到同样的效果,那么你可能需要找到一种不同的方法。你的midi库可能提供了一种异步发送笔记的方法,而不需要使用线程,但我不熟悉它,所以我不知道。
另请参阅:https://stackoverflow.com/search?q=%5Bandroid%5D%20midi%20delay
答案 1 :(得分:0)
正如我在评论中所说,它更像是一种与语言无关的东西。在最小化线程执行差距方面,不可能进行极简主义优化
可以尝试一下。
private static TestExecutorSerivice obj=new TestExecutorSerivice(3);;
Handler[] handlers = new Handler[3]; //same as above
for(int i = 0; i<handlers.length; i++)
handlers[i] = new Handler();
private void handlePlayButtonAction(ActionEvent event) throws InterruptedException {
Handler.click=System.nanoTime();
obj.run();
}
并在您的TestExecutorSerivice
班级run
方法
public void run() {
try {
pool.execute(handlers[(int)Thread.currentThread().getId()]);
} catch (Exception ex) {
pool.shutdown();
}
}