2012-05-04 42 views
0

起初,我这样做:在Java中,为什么我的多线程不工作?

public SpaceCanvas(){ 
    new Thread(new Runnable() {//this is the thread that triggers updates, no kidding 
     int fcount = 0; 

     @Override 
     public void run() { 
       System.out.println("Update thread started!"); 
       while(!Thread.interrupted()){ 
        fcount++; 
        while(players.iterator().hasNext()){ 
         players.iterator().next().update(fcount); 
        } 
        while(entities.iterator().hasNext()){ 
         entities.iterator().next().update(fcount); 
        } 
        System.out.println("About to paint"); 
        repaint(); 
        System.out.println("Done with paints"); 
        try { 
         Thread.sleep(500); 
        } catch (InterruptedException e) { 
         // TODO Auto-generated catch block 
         e.printStackTrace(); 
        } 
       } 
     } 
    }).start(); 
    players.add(new LocalPlayer(0, 9001, 0, 0, 0, 0, this, null)); 
} 

在我称之为SpaceCanvas事初始化。 但是,这不允许创建画布,因此它创建的小程序,因为线程不实际上异步运行。然后,我用“.run()”替换了“.start()”,该线程只运行一次,但SpaceCanvas完全初始化。

我做错了什么,我该如何解决这个问题?

回答

3

我不知道这种代码的工作,你期望它的方式:

while(players.iterator().hasNext()){ 
    players.iterator().next().update(fcount); 

players.iterator()将获取players收集一个新的迭代。如果集合中有0个项目,那么它将是false,但是如果有任何项目,则将处于无限循环中,每次都会创建一个新的迭代器。 players内部的iterator()调用也生成另一个新的迭代器对象。

我认为你应该做这样的事情:

Iterator iterator = players.iterator(); 
while (iterator.hasNext()) { 
    iterator.next().update(fcount); 
} 

这是您的entities循环一样好。一个更好的模式(如Java 5的)是使用for循环:

for (Player player : players) { 
    player.update(fcount); 
} 

此外,如果将多个线程访问这些集合,他们必须以某种方式​​。您可以使用并发集合,也可以确保访问(读取和写入)位于​​块内。

synchronized (players) { 
    for (Player player : players) { 
     player.update(fcount); 
    } 
} 
... 
// down in the outer thread 
synchronized (players) { 
    players.add(new LocalPlayer(0, 9001, 0, 0, 0, 0, this, null)); 
} 

显然entities将需要以同样的方式​​。

+0

我会尽快尝试这个,谢谢。 – striking

+0

你也可以使用'for(Iterator i = players.iterator(); i.hasNext();)i.next()。update(fcount);' – OldCurmudgeon

1
  1. 在这一千年,使用Swing(JApplet/JPanel),而不是AWT(Applet/Canvas
  2. 当使用Swing中,建立一个Swing Timer调用repaint()每500毫秒。
  3. (当使用Swing/Timer时)不要在EDT(Event Dispatch Thread)上调用Thread.sleep(n)

..can你画上一个JPanel?

当然可以。为此,请覆盖paintComponent(Graphics)方法。您也可以扩展JComponent并做同样的事情,但处理JComponent有一些怪癖,使JPanel成为更好的选择。

另一方面,完全有另一种方法。

  • 创建一个BufferedImage的大小需要的任何自定义图形所需。
  • 将图像添加到ImageIcon
  • 将图标添加到JLabel
  • 将标签添加到GUI。
  • 对每个Timer操作。
    • 请致电image.getGraphics()获取图面。
    • 复制你可能在paint()paintComponent()
      1. 做了(如果需要)删除所有以前的图纸。
      2. 绘制当前的自定义渲染。
    • dispose()Graphics图像的实例。
    • 电话label.repaint()
+0

我会尽快试试,谢谢。 另外,你可以使用JPanel吗?你可以在任何Swing上绘制任何东西吗?我想使用画布,以便我可以绘制它。 – striking

+0

查看更新。 –

+0

这真的非常有用(即使它没有解决我的问题),所以感谢让我保持在千禧年的编码标准之内! – striking

相关问题