在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中保留多个实例,因为我无法预测将并行调用多少个实例。
您会建议什么解决方案? 还有其他可能性吗?
提前非常感谢!
答案 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 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
Executors.newCachedThreadPool()
,例如来自Service
。
https://docs.oracle.com/javafx/2/threads/jfxpub-threads.htm中很好地涵盖了替代方案。
根据你所写的内容,我可能会选择{{1}},但两种选择都应该有效。