在Java中,为什么我的多线程不能工作?
起初我是这样做的:在Java中,为什么我的多线程不能工作?,java,multithreading,asynchronous,applet,graphics2d,Java,Multithreading,Asynchronous,Applet,Graphics2d,起初我是这样做的: 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!")
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的事物的初始值设定项中。
但是,这不允许创建画布,也不允许创建画布中的小程序,因为线程实际上不是异步运行的。然后,我将“.start()”替换为“.run()”,线程只运行了一次,但SpaceCanvas初始化得非常完美
我做错了什么,如何修复?我不确定这类代码的工作方式是否符合您的预期:
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);
}
这同样适用于实体
循环。更好的模式(从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));
}
显然,实体
需要以相同的方式进行同步。我不确定这类代码的工作方式是否符合您的预期:
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);
}
这同样适用于实体
循环。更好的模式(从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));
}
显然,实体
需要以相同的方式进行同步
在这个千年中,使用Swing(JApplet/JPanel
)而不是AWT(Applet/Canvas
)
使用Swing时,建立一个Swing计时器,每隔500毫秒调用一次repaint()
李>
(当使用Swing/定时器时
)不要调用EDT(事件调度线程)上的线程。sleep(n)
…你能在一张纸上画画吗
当然可以。为此,请重写paintComponent(Graphics)
方法。您也可以扩展JComponent
并执行相同的操作,但是处理JComponent
有一些怪癖,这使得JPanel
成为更好的扩展选择
另一方面,完全有另一种方法
- 创建一个
buffereImage
,大小与所需自定义图形的大小相同
- 将图像添加到
图像图标
- 将图标添加到
JLabel
- 将标签添加到GUI
- 在每个
计时器上
操作。
- 调用
image.getGraphics()
以获取绘图表面
- 复制您在
paint()
或paintComponent()中可能执行的操作
- (如果需要)删除所有以前的图形
- 绘制当前自定义渲染
- 图像的
图形实例的dispose()
- 调用
label.repaint()
在这个千年中,使用Swing(JApplet/JPanel
)而不是AWT(Applet/Canvas
)
使用Swing时,建立一个Swing计时器,每隔500毫秒调用一次repaint()
李>
(当使用Swing/定时器时
)不要调用EDT(事件调度线程)上的线程。sleep(n)
…你能在一张纸上画画吗
当然可以。为此,请重写paintComponent(Graphics)
方法。您也可以扩展JComponent
并执行相同的操作,但是处理JComponent
有一些怪癖,这使得JPanel
成为更好的扩展选择
另一方面,完全有另一种方法
- 创建一个
buffereImage
,大小与所需自定义图形的大小相同
- 将图像添加到
图像图标
- 将图标添加到
JLabel
- 将标签添加到GUI
- 在每个
计时器上
操作。
- 调用
image.getGraphics()
以获取绘图表面
- 复制您在
paint()
或paintComponent()中可能执行的操作
- (如果需要)删除所有以前的图形
- 绘制当前自定义渲染
- 图像的
图形实例的dispose()
- 调用
label.repaint()
我很快就会试试这个,谢谢。还有,你能在JPanel上画画吗?你能在秋千上画些什么吗?我想使用画布,这样我可以在上面画画。这真的,真的很有用,(即使它没有解决我的问题),所以谢谢你让我保持在千年的编码标准之内!我很快就会试试这个,谢谢。还有,你能在JPanel上画画吗?你能在秋千上画些什么吗?我想使用画布,这样我可以在上面画画。这真的,真的很有用,(即使它没有解决我的问题),所以谢谢你让我保持在千年的编码标准之内!您还可以将用于(迭代器i=players.Iterator();i.hasNext();)