如何使用 ExecutorService Java 减少到达 Runnable class 的 运行 方法的时间延迟

How to reduce the time delay to reach run method of Runnable class using ExecutorService Java

我试图实现一个实时执行的应用程序,其中按钮单击事件会将任务分配给线程,线程会调用 midi 方法 来播放一些音乐.单击按钮并稍有延迟时,必须立即开始播放音乐。 midi 代码在 Runnable class 的 运行 方法中实现。但是在按钮单击事件本身花费 超过 2 毫秒 之后到达 运行 方法的第一条语句。 我尝试使用 Executor Service,因为它可以收集新创建的线程并减少由线程引起的时间延迟。我是 ExecutorService 应用程序的新手。我观察到的是第一次单击按钮时花费了超过 2 毫秒,但是当它重新启动时延迟减少了。但在某个阶段它也增加到超过 4 毫秒。这种延迟如何每次都保持在不到一毫秒。有没有办法使用 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

正如我在评论中所说,它更像是一种独立于语言的东西。在最小化线程执行间隙方面不可能进行非常简单的优化

可以试试这个。

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 class 的 run 方法中

public void run() { 
  try {
     pool.execute(handlers[(int)Thread.currentThread().getId()]);
  } catch (Exception ex) {
     pool.shutdown();
  }
}

延迟可能是由于 OS 调度造成的,在这种情况下可能没有太多事情要做,或者因为线程池正忙于启动线程或因为您的池已被完全使用。

您可以尝试使用更大的池并预启动所有线程。类似于:

ThreadPoolExecutor tpe = new ThreadPoolExecutor(poolSize, poolSize, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>());
tpe.prestartAllCoreThreads();
pool = tpe;

例如池大小为 10。

(第一行相当于Executors.newFixedThreadPool)

如果您仍然观察到同样的效果,那么您可能需要寻找不同的方法。您的 midi 库可能提供了一种无需使用线程即可异步发送音符的方法,但我不熟悉它,所以我不知道。

另请参阅:https://whosebug.com/search?q=%5Bandroid%5D%20midi%20delay