【问题标题】:Most efficient way of calling (in) a new thread调用(in)新线程的最有效方式
【发布时间】:2018-04-20 15:56:36
【问题描述】:

在 JFX 应用程序中具有以下相当微不足道的意图:当在键盘上按下一个键并因此调用一个 handle(event ev) 方法时,我希望在另一个未使用的线程中发生某些事情。

到目前为止,我发现有三个选项:

要么直接在句柄中创建新线程:

public void handle(KeyEvent ke)
{
  new Thread(() -> {
    // THE CODE
    }).start();
  }
}

或者我在程序开始时启动一个不同的线程,看起来像这样:

public void run()
{
  while(true)
  {
    if (triggered)
    {
      // THE CODE
    }
  }
}

然后在handle() 方法中,我只是将“触发”字段设置为true。

第三种方法是创建尽可能多的扩展“线程”类的实例,以便并行执行,并在句柄()中使用它们的 start() 函数。

嗯,据我所知,前一种方法由于线程创建而具有很大的开销。

第二种方法在 99.9% 的时间里毫无意义地需要 CPU 资源。 这只能通过在循环中添加 sleep() 来削弱。

第三种方法似乎与第一种方法非常相似,因为大多数资源都是在调用 start() 时分配的,还是我错了? 该方法还有一个缺点是必须在内存中保留多个实例,因为我无法预测将并行调用多少个实例。

您会建议什么解决方案? 还有其他可能吗?

提前非常感谢!

【问题讨论】:

    标签: java multithreading javafx


    【解决方案1】:

    我建议将任务添加到ExecutorService 这用作后台线程池,不使用时处于空闲状态。然而,其中的线程被重用以提高效率。如果您不知道一次需要多少个线程,您可以使用缓存线程池。

    static final ExecutorService executor = Executors.newCachedThreadPool();
    
    public void handle(KeyEvent ke)
    {
        executor.execute(() -> {
            // THE CODE
        });
    }
    

    public void handle(KeyEvent ke)
    {
        executor.execute(this::task1);
    }
    
    void task1() 
    {
        // THE CODE
    }
    

    【讨论】:

      【解决方案2】:

      您可以使用ThreadPoolExecutor,这样可以避免:

      • 重复创建新线程
      • 不必要地检查triggered状态

      像这样:

      ExecutorService executor = executors.newcachedthreadpool();
      
      public void handle(KeyEvent ke)
      {
        Runnable runnable = new Runnable() {
            void run() {
                // code
            }
        }
        executor.execute(runnable);
      }
      

      【讨论】:

      • 我建议学习使用 lambda,因为大多数 IDE 现在都有自动重构来使用它们。 Java 10 也是当前版本;)
      • @PeterLawrey 是的,我正在努力。它看起来很酷。我的公司使用 jdk7 : (
      • 随着发布周期的加快,一些公司将很难保持最新状态。顺便说一句,Java 9 将结束公共支持,Java 10 将在 5 个月后结束。 :P
      【解决方案3】:

      您可以使用 JavaFX Service (https://docs.oracle.com/javase/8/javafx/api/javafx/concurrent/Service.html) 或创建 Task (https://docs.oracle.com/javase/8/javafx/api/javafx/concurrent/Task.html),然后手动提交新的 Thread 或使用 Executor,例如来自 @987654328 @。

      https://docs.oracle.com/javafx/2/threads/jfxpub-threads.htm 很好地介绍了替代方案。

      根据您所写的内容,我可能会选择Service,但两种选择都应该有效。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-01-19
        • 1970-01-01
        • 2014-03-13
        • 2010-09-06
        • 2013-12-09
        • 1970-01-01
        • 2011-07-07
        • 1970-01-01
        相关资源
        最近更新 更多