调用(in)新线程

时间:2018-04-20 15:56:37

标签: java multithreading javafx

在JFX应用程序中具有以下相当简单的意图:当在键盘上按下键并因此调用句柄(事件ev)方法时,我希望在不同的未使用的线程中发生某些事情。

到目前为止,我发现有三种选择:

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

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

或者我在programm上启动另一个线程,看起来像这样:

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

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

第三种方法是创建一个扩展“Thread”的类的实例,并根据需要并行执行,并在handle()中使用它们的start()函数。

嗯,从我看到的情况来看,由于线程创建,前一种方法会产生很大的开销。

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

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

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

提前非常感谢!

3 个答案:

答案 0 :(得分:3)

我建议将任务添加到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
}

答案 1 :(得分:1)

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

  • 重复创建新主题
  • 不必要地检查triggered状态

像这样:

ExecutorService executor = executors.newcachedthreadpool();

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

答案 2 :(得分:1)

您可以使用JavaFX Servicehttps://docs.oracle.com/javase/8/javafx/api/javafx/concurrent/Service.html)或创建Taskhttps://docs.oracle.com/javase/8/javafx/api/javafx/concurrent/Task.html),您可以使用新的Thread手动提交或使用Executor Executors.newCachedThreadPool(),例如来自Service

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

根据你所写的内容,我可能会选择{{1}},但两种选择都应该有效。