Java 8可能的双Lambda表达式
我正在创建一个模拟器,但为了简单起见,这是一个'游戏'。因此它有一个render()和一个update()函数。我一直在尝试在夏季练习lambda表达式,但似乎无法围绕做另一个lambda表达式的lambda表达式。我可能会说这不对,但我所要做的是启动两个线程,一个是环渲染,另一个是环更新。我可以远远得到这样的:Java 8可能的双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();
我知道我可以让我的渲染函数while循环,而我的更新函数while while循环只是将'void loop(Supplier arg)'代码复制到每个部分,但我想看看我是否可以用这种方式来完成。
我不需要一个确切的答案,我只是想指导一下我没有想到/我在想什么错。通过阅读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不允许:'this :: loop(this :: update)'?我注意到如果一个函数有一个参数,我必须像'() - > doFoo(arg)'一样引用它。为什么这样? –
a)你需要一个方法引用的目标类型来工作(对于'this :: loop'没有一个)和b)即使你有一个目标类型java也不支持curry作为语言功能,所以你需要以不同的方式实现它。 – fabian
您最后的想法是可以的,但是loop()方法应该将Runnable作为参数,而不是供应商,因为您要执行一个不带参数的函数,并且不返回任何内容,这就是Runnable的作用。因此它应该在每次迭代时调用可运行的run()。 –
首先,你为什么要考虑“睡眠循环”而不是使用定时器? – RealSkeptic
作为使用裸机线程的替代方案,您最好使用ExecutorServices并不断提交作业。这不会对lambda表达式有帮助,但它会使测试变得更容易(因为你可以很容易地用一个“当前线程”执行程序代替多线程执行程序服务。 – GhostCat