我正在创建一个模拟器,但为了简单起见,它是一个“游戏”。因此它有一个render()和update()函数。我一直试图在夏天练习lambda表达式,但我似乎无法绕着做另一个lambda表达式的lambda表达式。我可能说错了,但我要做的是启动两个线程,一个 循环呈现,另一个 循环更新。我可以做到这一点:
void render() {
//draw entities, etc.
}
void update() {
//update player/enemies, etc.
}
public GameFrame() {
/* init stuff */
Thread updateThread = new Thread(this::update);
Thread renderThread = new Thread(this::render);
}
这不是我想要的,因为它只运行更新并绘制一次,因此这只是两个线程,一个呈现一次,一个更新一次(没有循环)。我想创建一个能够执行以下操作的函数:
public void loop(Supplier< /*?*/ > arg) {
long startTime;
while(running) {
startTime = System.currentTimeMillis();
supplier.get(arg) // <- not sure about this either
try {
long sleepTime = 1000/FPS - (System.currentTimeMillis() - startTime);
if(sleepTime > 0)
Thread.sleep(sleepTime);
} catch(InterruptedException e) {
e.printStackTrace();
}
}
}
然后我会这样调用这个函数吗?
loop(this::update);
我相信这会导致提供的函数循环,因此我尝试了:
Thread updateThread = new Thread(this::loop(this::update));
甚至是这样的事情:
new Thread(() -> loop(this::update)).start();
我知道我可以在循环中创建渲染函数,而我的更新函数只需将'void loop(Supplier arg)'代码复制到每个部分中,但我想知道是否可以这样做反正。
我不需要一个确切的答案,我只想指导一下我没有想到的事情/我在想什么是错的。通过在oracle上阅读lambda表达式,我无法取得很大进展。
答案 0 :(得分:1)
Thread
构造函数需要Runnable
,这就是您想要重复执行的内容。因此,您不需要Supplier
作为loop
的参数类型,而是Runnable
。
public void loop(Runnable arg) {
long startTime;
while(running) {
startTime = System.currentTimeMillis();
arg.run();
try {
long sleepTime = 1000/FPS - (System.currentTimeMillis() - startTime);
if(sleepTime > 0)
Thread.sleep(sleepTime);
} catch(InterruptedException e) {
e.printStackTrace();
}
}
}
请注意,无法使用方法参考指定参数。这是无效的语法:
this::loop(this::update)
您希望线程执行的语句是:
loop(this::update);
所以你需要使用一个lambda表达式,并将此语句作为body作为Thread
构造函数的参数:
Thread updateThread = new Thread(() -> loop(this::update));
请注意,ScheduledExecutorService
提供了您在此处实施的计划。