繁体   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