我正在尝试同步这段代码:我想要的是Gioca等级直到类Gioco调用方法正常(罚款应该停止线程)但是当Gioca类调用run方法时它会在控制台上打印字符串“Fine”甚至可以说类Gioco还没有调用方法fine()。
public class Gioca implements Runnable
{
private int vite;
private int recuperi;
public Gioca()
{
vite=3;
recuperi=0;
}
public void gioca()
{
Thread t=new Thread(new Gioco(vite));
try
{
t.start();
t.join();
}
catch (Exception ex) {}
System.out.println("Fine");
}
@Override
public void run()
{
gioca();
}
}
public class Gioco extends Canvas implements ActionListener, KeyListener, Runnable
{
private int direzione;
private Timer timer;
private JFrame f;
private int vite;
private int velocità;
private int spazio;
private Personaggio p;
private int pos;
private LinkedList<Ostacolo> o;
private Random r;
private int po;
private Image imm1=new ImageIcon(this.getClass().getResource("images/sfondo.jpg")).getImage();
private Image imm2=new ImageIcon(this.getClass().getResource("images/cuore.png")).getImage();
public Gioco(int vite)
{
r=new Random();
try
{
File file=new File("images/punteggio.txt");
Scanner scanner=new Scanner(file);
spazio=scanner.nextInt();
}
catch (Exception e) {}
direzione=3;
this.vite=vite;
o=new LinkedList();
for(int i=0; i<20; i++)
o.add(new Ostacolo(Math.abs(400*i)+1000));
p=new Personaggio();
this.velocità=2;
timer=new Timer(10, this);
f=new JFrame("Gioco");
f.setSize(1000, 700);
f.setResizable(false);
f.setLocation(200,200);
f.add(this);
f.addKeyListener(this);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void actionPerformed(ActionEvent ae)
{
if(direzione==2)
{
velocità-=2;
if(velocità<2)
velocità=2;
}
if(direzione==1)
p.setY(5);
if(direzione==0)
p.setY(-5);
spazio+=velocità;
if(spazio%1000<10)
velocità++;
pos=(pos+velocità)%4500;
po=-pos;
for(int i=0; i<20; i++)
{
o.get(i).muovi(velocità);
if(o.get(i).getX()<-100)
{
o.remove(i);
o.add(new Ostacolo(i*400));
}
}
verificaCollisioni();
repaint();
}
public void verificaCollisioni()
{
for(int i=0; i<20; i++)
{
if(o.get(i).getX()>300 && o.get(i).getX()<350)
{
int r[]=o.get(i).getDimensioni();
if(r[0]<p.getY() && r[1]>p.getY())
{
}
else
fine();
}
}
}
private void fine()
{
try
{
Thread.sleep(3000);
}
catch(Exception e){}
timer.stop();
try
{
File file=new File("images/punteggio.txt");
file.createNewFile();
FileOutputStream f=new FileOutputStream(file);
f.flush();
String sPunteggio=String.valueOf(spazio);
byte[] scrivi=sPunteggio.getBytes();
f.write(scrivi);
}
catch(Exception e){}
f.dispose();
}
@Override
public void keyPressed(KeyEvent ke)
{
int c=ke.getKeyCode();
if(c == 40)
direzione=1;
if(c == 38)
direzione=0;
if(c==32)
direzione=2;
}
public void paint(Graphics g)
{
Image workspace=createImage(getWidth(),getHeight());
Graphics2D buffer=(Graphics2D) workspace.getGraphics();
buffer.drawImage(imm1, po, 0, this);
buffer.setColor(new Color(242, 54, 33));
buffer.setFont(new Font(Font.SANS_SERIF, Font.BOLD, 20));
buffer.drawString(""+(spazio/100), 10, 20);
buffer.drawImage(imm2, 940, 4, this);
buffer.setColor(new Color(13, 226, 13));
buffer.drawString(""+vite, 920, 20);
buffer.drawImage(p.getImage(), 300, p.getY(), this);
for(int i=0; i<20; i++)
{
Ostacolo tmp=o.get(i);
buffer.drawImage(tmp.getImage(), tmp.getX(),tmp.getY(), this);
}
Graphics2D g2=(Graphics2D)g;
g2.drawImage(workspace, 0, 0, this);
buffer.dispose();
}
public void update(Graphics g)
{
paint(g);
}
public void keyReleased(KeyEvent ke) {direzione=3;}
public void keyTyped(KeyEvent ke) {}
@Override
public void run()
{
f.setVisible(true);
timer.start();
}
}
此代码使用相同的说明,效果很好
public class Campana implements Runnable{
private String suono;
private int volte;
public Campana(String suono,int volte)
{
this.suono =suono;
this.volte=volte;
}
public void run()
{
for(int i=0;i<volte;i++) {
System.out.println((i+1)+" "+suono);
}
}
}
public class Suona {
public static void main(String args[]){
Thread campana1=new Thread(new Campana("din", 5));
Thread campana2=new Thread(new Campana("don", 5));
Thread campana3=new Thread(new Campana("dan", 5));
try {
campana1.start();
campana1.join();
campana2.start();
campana2.join();
campana3.start();
campana3.join();
} catch (InterruptedException ex) {
Logger.getLogger(Suona.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
答案 0 :(得分:2)
t.join();
等待run
中的Gioco
终止。该方法在
f.setVisible(true);
timer.start();
已经完成,这将非常快,因为Timer
将运行actionPerformed
与调用timer.start();
的线程不同的线程。它不会等到计时器停止。您可以通过在run
方法中引入某种形式的同步来解决此问题。我不建议使用while循环,因为这会浪费资源来运行循环。相反,请考虑使用CountDownLatch
(javadoc link):
将此添加到Gioco
:
private final CountDownLatch doneSignal = new CountDownLatch(1);
在fine()
致电doneSignal.countDown()
结束时。最后将run()
中的Gioco
方法更改为以下内容:
@Override
public void run()
{
f.setVisible(true);
timer.start();
try {
doneSignal.await();
} catch (InterruptedException ex) {}//Logg this or something. Shouldn't really ever happen.
}