2016-08-17 68 views
1

我正在创建一个模拟器,但为了简单起见,这是一个'游戏'。因此它有一个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表达式,我无法取得很大进展。

+3

您最后的想法是可以的,但是loop()方法应该将Runnable作为参数,而不是供应商,因为您要执行一个不带参数的函数,并且不返回任何内容,这就是Runnable的作用。因此它应该在每次迭代时调用可运行的run()。 –

+4

首先,你为什么要考虑“睡眠循环”而不是使用定时器? – RealSkeptic

+2

作为使用裸机线程的替代方案,您最好使用ExecutorServices并不断提交作业。这不会对lambda表达式有帮助,但它会使测试变得更容易(因为你可以很容易地用一个“当前线程”执行程序代替多线程执行程序服务。 – GhostCat

回答

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表达式这个说法是身体为Thread构造函数的参数:

Thread updateThread = new Thread(() -> loop(this::update)); 

请注意,ScheduledExecutorService提供了您在此处执行的调度类型。

+0

你会碰巧知道为什么Java不允许:'this :: loop(this :: update)'?我注意到如果一个函数有一个参数,我必须像'() - > doFoo(arg)'一样引用它。为什么这样? –

+0

a)你需要一个方法引用的目标类型来工作(对于'this :: loop'没有一个)和b)即使你有一个目标类型java也不支持curry作为语言功能,所以你需要以不同的方式实现它。 – fabian