【问题标题】:How to pause and resume a thread in Java game developmentJava游戏开发中如何暂停和恢复线程
【发布时间】:2014-06-04 04:30:38
【问题描述】:

我需要知道如何在检查条件后暂停线程并恢复它。

  Thread t = new Thread () {
  public void run() { 
    while(true) {
      update();
      repaint();
      try {  
        Thread.sleep(50);
      } catch(InterruptedException e){}
    }
  }


       };

上面的代码是我的游戏循环,如果检查任何条件,我需要暂停和恢复。

我认为线程只能启动一次,因此我们不能使用suspend() 或resume(),因为它已被弃用。

// all imports goes here /** Bouncing Ball (Animation) via custom thread */

public class JavaApplication12 extends JFrame implements KeyListener{ 
    // Define named-constants
    private static final int CANVAS_WIDTH = 640;
    private static final int CANVAS_HEIGHT = 600;
    private static final int UPDATE_INTERVAL = 10;
    milliseconds int xx = 200; int yy = 500;
    Shape a1; Shape a2; float das[] = {10.0f}; int f = 20;

    boolean r = true;

    Font font = new Font("Arial",Font.ROMAN_BASELINE,f);

    BasicStroke color = new BasicStroke (10,BasicStroke.CAP_ROUND,BasicStroke.JOIN_BEVEL,10.0f,das,0.0f);
    GradientPaint dash = new GradientPaint(0,0,Color.BLUE,100,0,Col or.CYAN);

    Rectangle2D a3;

    Rectangle2D a12;
    Rectangle2D a4;
    Rectangle2D a5;
    Rectangle2D a6;
    Rectangle2D a7;
    Rectangle2D a8;
    Rectangle2D a9;
    Rectangle2D a10;
    Rectangle2D a11; Rectangle2D a13;
    Rectangle2D a14;
    Rectangle2D a15; Rectangle2D a16;
    Rectangle2D a17; Rectangle2D a18;
    Rectangle2D a19; Rectangle2D a20;
    Rectangle2D a21; Rectangle2D a22;
    Rectangle2D a23;
    Rectangle2D a25;

    ArrayList s = new ArrayList();

    Color c2 = Color.RED;

    private DrawCanvas canvas; //the drawing canvas (extends JPanel)

    // Attributes of moving object
    // top-left (x, y)
    private int x = 200;
    private int y = 480;
    //width and height
    private int size = 20;
    //moving speed in x and y directions
    private int xSpeed = 3;
    //displacement per step in x and y
    private int ySpeed = 5; 

    /** Constructor to setup the GUI components */
    public JavaApplication12() {
        canvas = new DrawCanvas();

        canvas.setPreferredSize(new Dimension(CANVAS_WIDTH, CANVAS_HEIGHT));

        this.setContentPane(canvas);

        this.setDefaultCloseOperation(EXIT_ON_ CLOSE);
        this.pack();
        this.setTitle("Bouncing Ball");
        this.setVisible(true); addKeyListener(this);

        fun();

    }

    Thread updateThread = new Thread() { @Override public void run() {

        while (r) { update(); // update the (x, y) position

            repaint(); // Refresh the JFrame. Called back paintComponent()

            try { // Delay and give other thread a chance to run

                Thread.sleep(UPDATE_INTERVAL); //milliseconds

            } catch (InterruptedException ignore) {} } }

    };

    /** Update the (x, y) position of the moving object */
    public void update() { 
        x += xSpeed; y += ySpeed; 
        if (x > CANVAS_WIDTH - size || x < 0) { xSpeed = -xSpeed; } 
        if (y > CANVAS_HEIGHT - 80 || y < 0) { ySpeed = -ySpeed;  }

    }

@Override public void keyTyped(KeyEvent ke) { }

@Override

@SuppressWarnings({"deprecation", "deprecation"}) 
public void keyPressed(KeyEvent ke) { 
    int keycode = ke.getKeyCode(); 
    if(keycode == KeyEvent.VK_LEFT) { xx = xx-15; } 
    if(keycode == KeyEvent.VK_SPACE) { 
        if(r == true) { 
            //r = false;
            updateThread.start();
        }

    } 
    if(keycode == KeyEvent.VK_ESCAPE) {    }

    if(keycode == KeyEvent.VK_RIGHT) { xx = xx+15; }

}

@Override public void keyReleased(KeyEvent ke) { 
    // throw new UnsupportedOperationException("Not supported yet.");
}

/** DrawCanvas (inner class) is a JPanel used for custom drawing */
    class DrawCanvas extends JPanel { 
        private static final long serialVersionUID = 1L; 
        int i=0; 
        int liv = 3;

        @Override

        public void paintComponent(Graphics g) { super.paintComponent(g); //paint parent's background Graphics2D d = (Graphics2D)g;

            a1 = new Ellipse2D.Double(x,y,size,size);
            d.drawLine(0,540,640,540);
            for(Rectangle2D r : s){ 
                    d.setStroke(color);
                    //d.setPaint(dash);
                    d.draw(r); 
            }
            a25 = new Rectangle2D.Double(0,540,1000,10);
            d.draw(a25);
            setBackground(Color.WHITE);

                d.setColor(Color.BLUE);

                a2 = new RoundRectangle2D.Double(xx,yy,120,10,2 0,20);

                d.fill(a1); d.setPaint(c2);
                d.fill(a2); d.setFont(font);
                d.drawString("Score : "+i,5,575);
                d.drawString("Life : "+liv,550,575);

                if(a1.intersects(a25.getBounds())) {
                    if(liv>0) { liv = liv-1;}

                    if(liv == 0) { //JOptionPane.showMessageDialog(null, "","",0);

                    } }

                if(s.contains(a3) && a1.intersects(a3.getBounds())) { 
                    i = i+10; s.remove(a3);
                    ySpeed = -ySpeed;
                    try { m(); } 
                    catch (UnsupportedAudioFileException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } catch (IOException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } catch (LineUnavailableException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } } if(s.contains(a4) && a1.intersects(a4.getBounds())) { i = i+10; s.remove(a4);ySpeed = -ySpeed;

                    try { m();

                    } catch (UnsupportedAudioFileException ex) {

                        Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } catch (IOException ex) {

                        Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } catch (LineUnavailableException ex) {

                        Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } } if(s.contains(a5) && a1.intersects(a5.getBounds())) { i = i+10; s.remove(a5);ySpeed = -ySpeed; try { m(); } catch (UnsupportedAudioFileException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } catch (IOException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } catch (LineUnavailableException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } } if(s.contains(a6) && a1.intersects(a6.getBounds())) { i = i+10; s.remove(a6);ySpeed = -ySpeed; try { m(); } catch (UnsupportedAudioFileException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } catch (IOException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } catch (LineUnavailableException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } } if(s.contains(a7) && a1.intersects(a7.getBounds())) { i = i+10; s.remove(a7);ySpeed = -ySpeed; try { m(); } catch (UnsupportedAudioFileException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } catch (IOException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } catch (LineUnavailableException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } } if(s.contains(a8) && a1.intersects(a8.getBounds())) { i = i+10; s.remove(a8);ySpeed = -ySpeed; try { m(); } catch (UnsupportedAudioFileException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } catch (IOException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } catch (LineUnavailableException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); }

                } if(s.contains(a9) && a1.intersects(a9.getBounds())) { i = i+10; s.remove(a9);ySpeed = -ySpeed; try { m(); } catch (UnsupportedAudioFileException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } catch (IOException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } catch (LineUnavailableException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } } if(s.contains(a10) && a1.intersects(a10.getBounds())) { i = i+10; s.remove(a10);ySpeed = -ySpeed; try { m(); } catch (UnsupportedAudioFileException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } catch (IOException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } catch (LineUnavailableException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } } if(s.contains(a11) && a1.intersects(a11.getBounds())) { i = i+10; s.remove(a11);ySpeed = -ySpeed; try { m(); } catch (UnsupportedAudioFileException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } catch (IOException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } catch (LineUnavailableException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } } if(s.contains(a12) && a1.intersects(a12.getBounds())) { i = i+10; s.remove(a12);ySpeed = -ySpeed; try { m(); } catch (UnsupportedAudioFileException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } catch (IOException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } catch (LineUnavailableException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } } if(s.contains(a13) && a1.intersects(a13.getBounds())) { i = i+10; s.remove(a13);ySpeed = -ySpeed; try { m(); } catch (UnsupportedAudioFileException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } catch (IOException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } catch (LineUnavailableException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } } if(s.contains(a14) && a1.intersects(a14.getBounds())) { i = i+10; s.remove(a14);ySpeed = -ySpeed; try { m(); } catch (UnsupportedAudioFileException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } catch (IOException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } catch (LineUnavailableException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } } if(s.contains(a15) && a1.intersects(a15.getBounds())) { i = i+10; s.remove(a15);ySpeed = -ySpeed; try { m(); } catch (UnsupportedAudioFileException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } catch (IOException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } catch (LineUnavailableException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } }

                if(s.contains(a16) && a1.intersects(a16.getBounds())) { i = i+10; s.remove(a16);ySpeed = -ySpeed; try { m(); } catch (UnsupportedAudioFileException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } catch (IOException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } catch (LineUnavailableException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } }

                if(s.contains(a17) && a1.intersects(a17.getBounds())) { i = i+10; s.remove(a17);ySpeed = -ySpeed; try { m(); } catch (UnsupportedAudioFileException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } catch (IOException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } catch (LineUnavailableException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } }

                if(s.contains(a18) && a1.intersects(a18.getBounds())) { i = i+10; s.remove(a18);ySpeed = -ySpeed; try { m(); } catch (UnsupportedAudioFileException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } catch (IOException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } catch (LineUnavailableException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } }

                if(s.contains(a19) && a1.intersects(a19.getBounds())) { i = i+10; s.remove(a19);ySpeed = -ySpeed; try { m(); } catch (UnsupportedAudioFileException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } catch (IOException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } catch (LineUnavailableException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } }

                if(s.contains(a20) && a1.intersects(a20.getBounds())) { i = i+10; s.remove(a20);ySpeed = -ySpeed; try { m(); } catch (UnsupportedAudioFileException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } catch (IOException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } catch (LineUnavailableException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } }

                if(s.contains(a21) &&a1.intersects(a21)) { i = i+10; s.remove(a21);ySpeed = -ySpeed; try { m(); } catch (UnsupportedAudioFileException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } catch (IOException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } catch (LineUnavailableException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } }

                if(s.contains(a22) && a1.intersects(a22)) { i = i+10; s.remove(a22); ySpeed = -ySpeed; try { m(); } catch (UnsupportedAudioFileException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } catch (IOException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } catch (LineUnavailableException ex) {

                    Logger.getLogger(JavaApplication12.cla ss.getName()).log (Level.SEVERE, null, ex); } }

                collide(); } public void m() throws UnsupportedAudioFileException, IOException, LineUnavailableException { String a = "chimes.wav"; AudioInputStream aa = AudioSystem.getAudioInputStream(new File (a).getAbsoluteFile()); Clip c = AudioSystem.getClip(); c.open(aa); c.start(); }

    }

    public final void fun() { 
        a3 = new Rectangle2D.Double(20,15,100,20);
        a4 = new Rectangle2D.Double(150,15,100,20);
        a5 = new Rectangle2D.Double(280,15,100,20);

        a6 = new Rectangle2D.Double(400,15,100,20);
        a7 = new Rectangle2D.Double(530,15,100,20);

        a8 = new Rectangle2D.Double(20,50,100,20);
        a9 = new Rectangle2D.Double(150,50,100,20);
        a10 = new Rectangle2D.Double(280,50,100,20);
        a12 = new Rectangle2D.Double(400,50,100,20);
        a11 = new Rectangle2D.Double(530,50,100,20);

        a13 = new Rectangle2D.Double(20,85,100,20);
        a14 = new Rectangle2D.Double(150,85,100,20);
        a15 = new Rectangle2D.Double(280,85,100,20);
        a16 = new Rectangle2D.Double(400,85,100,20);
        a17 = new Rectangle2D.Double(530,85,100,20);

        a18 = new Rectangle2D.Double(20,120,100,20);
        a19 = new Rectangle2D.Double(150,120,100,20);
        a20 = new Rectangle2D.Double(280,120,100,20);
        a21 = new Rectangle2D.Double(400,120,100,20);
        a22 = new Rectangle2D.Double(530,120,100,20);

        s.add(a3); s.add(a4); s.add(a5); s.add(a6);
        s.add(a7); s.add(a8); s.add(a9); s.add(a10);
        s.add(a11); s.add(a12);
        s.add(a13); s.add(a14); s.add(a15); s.add(a16);
        s.add(a17); s.add(a18);
        s.add(a19); s.add(a20); s.add(a21); s.add(a22); }

    public void collide() {

        if(a2.intersects(a1.getBounds())) {

            xSpeed = xSpeed; ySpeed = -ySpeed;

        } }

    public static void main(String[] args) { 
        // Run GUI codes in Event-Dispatching thread for thread safety 
        SwingUtilities.invokeLater(new Runnable() { 
            @Override public void run() { 
                new JavaApplication12(); // Let the constructor do the job
            }
        });
    }
}

【问题讨论】:

  • 您需要从该线程本身还是从其他线程暂停?
  • 您需要向我们提供有关您的方案的更多信息。给我们一个条件变量来处理。在代码中声明变量,指明要进行条件检查和暂停的位置。
  • 我在这里有我的代码,但由于我从手机上使用网络,所以请管理一下。
  • 当用户按下退出键时,如果按下相同的键,游戏应该会再次暂停。
  • 我和妻子出去了,我已经尝试过回答。希望能解决您的问题。

标签: java multithreading wait notify


【解决方案1】:

除了sleep(),Thread 还有另外两个静态方法wait() 和await() 专门用于此目的。

如果您希望 Foo 类的实例暂停并等待 Bar 类的实例告诉它唤醒:

//in Foo class
synchronized void doStuffAndWait() throws InterruptedException {
    //do stuff
    while(!someCondition) { 
           wait();
           System.out.println("I woke up!");
    }

//in Bar class; 
synchronized void wakeFooUp(Foo foo){
    foo.someCondition = true; 
    foo.notify();
}

当您的 foo 实例完成操作并且 someCondition 评估为 false 时,它​​会进入 while 循环。 while 循环让一些人望而却步,因为发生的事情并不是传统意义上的真正“迭代”。

举例说明:如果您在循环中调用Thread.sleep(1000),则每次迭代之间会有1 秒的暂停。同样,假设someCondition 的计算结果为假,则线程在该循环的第一次迭代中进入睡眠状态。但它不是在固定的时间内休眠,而是无限期地休眠——直到有其他东西调用notify()。当它醒来时,它只是在wait() 之后继续下一行(就像对sleep() 的调用完成时一样)。在这种情况下,它会打印“我醒来”,然后再次检查 someCondition。如果您的Bar 在通知它之前没有将该条件设置为真,它就会重新进入睡眠状态。

我应该注意到,这是一个非常简单的介绍性解释,而我们正在谈论的 - 称为 concurrency - 是一个众所周知的复杂话题。

【讨论】:

    【解决方案2】:

    使用AtomicBoolean 对象作为您可以等待的锁。

    下面的代码应该在每次按下转义键时翻转AtomicBooleanis_running。(我们在is_running.set(!is_running.get());这一行上翻转它...)当它从true翻转到false时,下一个while(r) 在 updateThread 中的迭代将 wait 在 synchronized 块内。下次在 is_running 对象上调用 notify_all 方法时,它将被唤醒。(下次按下退出键时会发生这种情况)。所以当再次按下 Escape 键时,is_running 标志再次翻转,notify_all 方法调用将唤醒updateThread,此时continue 语句会将其带到顶部while 循环并在检查is_running 以确保标志为真之后,它将继续执行update() 和repaint() 代码并继续循环,直到再次翻转标志。

    我显然没有测试过这段代码,如果代码有错误,请告诉我。

    JavaApplication12 extends JFrame implements KeyListener {
    ...
    AtomicBoolean is_running(true);
    ...
    Thread updateThread = new Thread() {
      @Override public void run() {
        while (r) {
          synchronized(is_running) {
            if(!is_running.get()) {
              is_running.wait();
              continue;
            }
          }
          update(); // update the (x, y) position
          repaint(); // Refresh the JFrame. Called back paintComponent()
          try { // Delay and give other thread a chance to run
            Thread.sleep(UPDATE_INTERVAL); //milliseconds
          } catch (InterruptedException ignore) {}
        }
      }
    };
    ...
    @SuppressWarnings({"deprecation", "deprecation"}) public void keyPressed(KeyEvent ke) {
      ...
      } if(keycode == KeyEvent.VK_ESCAPE) {
        synchronized(is_running)
          is_running.set(!is_running.get());
          is_running.notify_all();
        }
      }
      ...
    }
    

    【讨论】:

    • 没有兄弟它不起作用,在添加代码 thr thread 后根本没有开始。如何从 true 翻转到 false 我不明白这个逻辑。
    • @user3705482 我忘了像AtomicBoolean is_running(true); 一样初始化is_running 我已经在代码中修复了这个问题。它现在有效吗? is_running 被is_running.set(!is_running.get()); 行翻转
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-02
    • 2018-12-01
    • 1970-01-01
    • 2015-02-21
    • 2011-03-06
    相关资源
    最近更新 更多