簡體   English   中英

在Java中,為什么我的多線程無法正常工作?

[英]In Java, why is my multithreading not working?

首先,我這樣做:

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。 但是,這不允許創建畫布及其內部的applet,因為Thread 實際上並不異步運行。 然后,我將“ .start()”替換為“ .run()”,該線程只運行了一次,但SpaceCanvas初始化完美。

我做錯了什么,該如何解決?

我不確定這種代碼是否可以按您期望的方式工作:

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

players.iterator()players集合獲取一個新的迭代器。 如果集合中有0個項目,那么它將為false但是如果有任何項目,您將處於無限循環中,每次都創建一個新的迭代器。 players iterator()內部的iterator()調用也會生成另一個新的迭代器對象。

我認為您應該執行以下操作:

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

entities循環也是如此。 更好的模式(從Java 5開始)是使用for循環:

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

另外,如果多個線程正在訪問這些集合,則必須以某種方式synchronized 您可以使用並發集合,也可以確保每次訪問(讀取和寫入)都在synchronized塊內。

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將需要以相同的方式進行synchronized

  1. 在這個千年中,使用Swing( JApplet/JPanel )而不是AWT( Applet/Canvas
  2. 使用Swing時,請建立一個Swing Timer ,每500毫秒調用一次repaint()
  3. (使用Swing / Timer )請勿在EDT(事件調度線程)上調用Thread.sleep(n) )。

..您可以使用JPanel嗎?

當然可以 為此,請重寫paintComponent(Graphics)方法。 您也可以擴展JComponent並執行相同的操作,但是處理JComponent會有一些怪癖,使JPanel成為擴展的更好選擇。

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

  • 創建所需的任何自定義圖形所需大小的BufferedImage
  • 將圖像添加到ImageIcon
  • 將圖標添加到JLabel
  • 將標簽添加到GUI。
  • 在每個Timer動作上。
    • 調用image.getGraphics()獲得繪圖表面。
    • 復制您可能在paint()paintComponent()所做的工作
      1. (如果需要)刪除所有先前的圖形。
      2. 繪制當前的自定義渲染。
    • 圖像的Graphics實例的dispose()
    • 調用label.repaint()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM