2012-05-04 73 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

相關問題