简体   繁体   中英

In Java, why is my multithreading not working?

At first I did this:

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));
}

in the initializer of a thing I call a SpaceCanvas. However, that doesn't allow the canvas, and therefore the applet it is within, to be created, because the Thread doesn't actually run asynchronously. Then, I replaced ".start()" with ".run()" and the thread only ran once, but the SpaceCanvas initialized perfectly.

What did I do wrong, and how do I fix this?

I'm not sure this sort of code works the way you expect it to:

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

players.iterator() gets a new iterator for the players collection. If there are 0 items in the collection then it will be false but if there are any items, you will be in an infinite loop, creating a new iterator each time. The iterator() call inside of players generates another new iterator object as well.

I think you should doing something like:

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

This is the same with your entities loop as well. A better pattern (as of Java 5) is to use the for loop:

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

Also, if multiple threads are accessing these collections, they have to be somehow synchronized . You can either use a concurrent collection or you have to make sure every access (read and write) is within a synchronized block.

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));
}

Obviously the entities will need to be synchronized in the same manner.

  1. In this millennium, use Swing ( JApplet/JPanel ) rather than AWT ( Applet/Canvas )
  2. When using Swing, establish a Swing Timer that calls repaint() every 500 msec.
  3. (When using Swing/ Timer ) Don't call Thread.sleep(n) on the EDT (Event Dispatch Thread).

..can you draw on a JPanel?

Sure thing. To do so, override the paintComponent(Graphics) method. You might also extend a JComponent and do the same, but there are some quirks to dealing with a JComponent that make the JPanel the better choice to extend.

On the other hand, there is another approach entirely.

  • Create a BufferedImage of the size required for whatever custom graphic is needed.
  • Add the image to an ImageIcon .
  • Add the icon to a JLabel .
  • Add the label to the GUI.
  • On each Timer action.
    • Call image.getGraphics() to obtain the drawing surface.
    • Replicate what you might have done in paint() or paintComponent()
      1. (If needed) erase all previous drawing.
      2. Draw the current custom rendering.
    • dispose() of the Graphics instance of the image.
    • call label.repaint()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM