我正在创建一个模拟器,但为了简单起见,它是一个“游戏”。因此它有一个 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)”代码复制到每个部分来制作我的渲染函数 while 循环和我的更新函数 while 循环,但我想看看是否可以这样做无论如何。
我不需要确切的答案,我只是想要一些关于我没有想到的/我正在考虑错误的事情的指导。通过阅读 Oracle 上的 lambda 表达式,我并没有取得太大进展。
最佳答案
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 表达式,将此语句作为主体作为 Thread
构造函数的参数:
Thread updateThread = new Thread(() -> loop(this::update));
请注意 ScheduledExecutorService
提供您在此处实现的调度类型。
关于Java 8 可能的双 Lambda 表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38989393/